From 40a433c9e0048d4b892aee2ca124ef8abe15136e Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Mon, 16 Jan 2012 09:44:35 +0000 Subject: [PATCH] Split NumberDictionary into a randomly seeded and an unseeded version. We don't want to randomize the stub cache. Review URL: http://codereview.chromium.org/9174023 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10402 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/macro-assembler-arm.cc | 12 +- src/code-stubs.cc | 6 +- src/elements.cc | 19 +-- src/factory.cc | 32 +++- src/factory.h | 15 +- src/heap.cc | 8 +- src/heap.h | 8 +- src/ia32/macro-assembler-ia32.cc | 12 +- src/incremental-marking.cc | 2 +- src/mips/macro-assembler-mips.cc | 12 +- src/objects-debug.cc | 2 +- src/objects-inl.h | 34 ++--- src/objects.cc | 241 +++++++++++++++++++------------ src/objects.h | 71 ++++++--- src/profile-generator.cc | 6 +- src/runtime.cc | 57 ++++---- src/stub-cache.cc | 35 +++-- src/type-info.cc | 6 +- src/type-info.h | 2 +- src/v8globals.h | 3 +- src/x64/macro-assembler-x64.cc | 14 +- 21 files changed, 369 insertions(+), 228 deletions(-) diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index fcb82994f..fa97611cf 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -1472,7 +1472,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, GetNumberHash(t0, t1); // Compute the capacity mask. - ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); + ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int sub(t1, t1, Operand(1)); @@ -1483,17 +1483,17 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, mov(t2, t0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i))); + add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); } and_(t2, t2, Operand(t1)); // Scale the index by multiplying by the element size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 // Check if the key is identical to the name. add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); - ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset)); + ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); cmp(key, Operand(ip)); if (i != kProbes - 1) { b(eq, &done); @@ -1506,14 +1506,14 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Check that the value is a normal property. // t2: elements + (index * kPointerSize) const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; ldr(t1, FieldMemOperand(t2, kDetailsOffset)); tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); b(ne, miss); // Get the value at the masked, scaled index and return. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; ldr(result, FieldMemOperand(t2, kValueOffset)); } diff --git a/src/code-stubs.cc b/src/code-stubs.cc index 85410c3cc..5fa9a2b5c 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -40,7 +40,7 @@ namespace internal { bool CodeStub::FindCodeInCache(Code** code_out) { Heap* heap = Isolate::Current()->heap(); int index = heap->code_stubs()->FindEntry(GetKey()); - if (index != NumberDictionary::kNotFound) { + if (index != UnseededNumberDictionary::kNotFound) { *code_out = Code::cast(heap->code_stubs()->ValueAt(index)); return true; } @@ -132,9 +132,9 @@ Handle CodeStub::GetCode() { AddToSpecialCache(new_object); } else { // Update the dictionary and the root in Heap. - Handle dict = + Handle dict = factory->DictionaryAtNumberPut( - Handle(heap->code_stubs()), + Handle(heap->code_stubs()), GetKey(), new_object); heap->public_set_code_stubs(*dict); diff --git a/src/elements.cc b/src/elements.cc index fd2b6d248..e54ec6269 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -549,11 +549,11 @@ class PixelElementsAccessor class DictionaryElementsAccessor : public ElementsAccessorBase { + SeededNumberDictionary> { public: // Adjusts the length of the dictionary backing store and returns the new // length according to ES5 section 15.4.5.2 behavior. - static MaybeObject* SetLengthWithoutNormalize(NumberDictionary* dict, + static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict, JSArray* array, Object* length_object, uint32_t length) { @@ -619,9 +619,10 @@ class DictionaryElementsAccessor if (is_arguments) { backing_store = FixedArray::cast(backing_store->get(1)); } - NumberDictionary* dictionary = NumberDictionary::cast(backing_store); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(backing_store); int entry = dictionary->FindEntry(key); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* result = dictionary->DeleteProperty(entry, mode); if (result == heap->true_value()) { MaybeObject* maybe_elements = dictionary->Shrink(key); @@ -654,7 +655,7 @@ class DictionaryElementsAccessor protected: friend class ElementsAccessorBase; + SeededNumberDictionary>; virtual MaybeObject* Delete(JSObject* obj, uint32_t key, @@ -662,12 +663,12 @@ class DictionaryElementsAccessor return DeleteCommon(obj, key, mode); } - static MaybeObject* Get(NumberDictionary* backing_store, + static MaybeObject* Get(SeededNumberDictionary* backing_store, uint32_t key, JSObject* obj, Object* receiver) { int entry = backing_store->FindEntry(key); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* element = backing_store->ValueAt(entry); PropertyDetails details = backing_store->DetailsAt(entry); if (details.type() == CALLBACKS) { @@ -682,7 +683,7 @@ class DictionaryElementsAccessor return obj->GetHeap()->the_hole_value(); } - static uint32_t GetKeyForIndex(NumberDictionary* dict, + static uint32_t GetKeyForIndex(SeededNumberDictionary* dict, uint32_t index) { Object* key = dict->KeyAt(index); return Smi::cast(key)->value(); @@ -895,7 +896,7 @@ MaybeObject* ElementsAccessorBase:: if (length->IsNumber()) { uint32_t value; if (length->ToArrayIndex(&value)) { - NumberDictionary* dictionary; + SeededNumberDictionary* dictionary; MaybeObject* maybe_object = array->NormalizeElements(); if (!maybe_object->To(&dictionary)) return maybe_object; Object* new_length; diff --git a/src/factory.cc b/src/factory.cc index 630d9456a..0b796350d 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -77,11 +77,21 @@ Handle Factory::NewStringDictionary(int at_least_space_for) { } -Handle Factory::NewNumberDictionary(int at_least_space_for) { +Handle Factory::NewSeededNumberDictionary( + int at_least_space_for) { ASSERT(0 <= at_least_space_for); CALL_HEAP_FUNCTION(isolate(), - NumberDictionary::Allocate(at_least_space_for), - NumberDictionary); + SeededNumberDictionary::Allocate(at_least_space_for), + SeededNumberDictionary); +} + + +Handle Factory::NewUnseededNumberDictionary( + int at_least_space_for) { + ASSERT(0 <= at_least_space_for); + CALL_HEAP_FUNCTION(isolate(), + UnseededNumberDictionary::Allocate(at_least_space_for), + UnseededNumberDictionary); } @@ -1071,13 +1081,23 @@ Handle Factory::Uint32ToString(uint32_t value) { } -Handle Factory::DictionaryAtNumberPut( - Handle dictionary, +Handle Factory::DictionaryAtNumberPut( + Handle dictionary, + uint32_t key, + Handle value) { + CALL_HEAP_FUNCTION(isolate(), + dictionary->AtNumberPut(key, *value), + SeededNumberDictionary); +} + + +Handle Factory::DictionaryAtNumberPut( + Handle dictionary, uint32_t key, Handle value) { CALL_HEAP_FUNCTION(isolate(), dictionary->AtNumberPut(key, *value), - NumberDictionary); + UnseededNumberDictionary); } diff --git a/src/factory.h b/src/factory.h index 343113686..8725b67ec 100644 --- a/src/factory.h +++ b/src/factory.h @@ -54,7 +54,11 @@ class Factory { int size, PretenureFlag pretenure = NOT_TENURED); - Handle NewNumberDictionary(int at_least_space_for); + Handle NewSeededNumberDictionary( + int at_least_space_for); + + Handle NewUnseededNumberDictionary( + int at_least_space_for); Handle NewStringDictionary(int at_least_space_for); @@ -432,8 +436,13 @@ class Factory { Handle stack_trace, Handle stack_frames); - Handle DictionaryAtNumberPut( - Handle, + Handle DictionaryAtNumberPut( + Handle, + uint32_t key, + Handle value); + + Handle DictionaryAtNumberPut( + Handle, uint32_t key, Handle value); diff --git a/src/heap.cc b/src/heap.cc index 6295788f0..3c871e270 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -2463,18 +2463,18 @@ bool Heap::CreateInitialObjects() { // Allocate the code_stubs dictionary. The initial size is set to avoid // expanding the dictionary during bootstrapping. - { MaybeObject* maybe_obj = NumberDictionary::Allocate(128); + { MaybeObject* maybe_obj = UnseededNumberDictionary::Allocate(128); if (!maybe_obj->ToObject(&obj)) return false; } - set_code_stubs(NumberDictionary::cast(obj)); + set_code_stubs(UnseededNumberDictionary::cast(obj)); // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial size // is set to avoid expanding the dictionary during bootstrapping. - { MaybeObject* maybe_obj = NumberDictionary::Allocate(64); + { MaybeObject* maybe_obj = UnseededNumberDictionary::Allocate(64); if (!maybe_obj->ToObject(&obj)) return false; } - set_non_monomorphic_cache(NumberDictionary::cast(obj)); + set_non_monomorphic_cache(UnseededNumberDictionary::cast(obj)); { MaybeObject* maybe_obj = AllocatePolymorphicCodeCache(); if (!maybe_obj->ToObject(&obj)) return false; diff --git a/src/heap.h b/src/heap.h index 6dc9d6111..a1a53db4a 100644 --- a/src/heap.h +++ b/src/heap.h @@ -146,8 +146,8 @@ inline Heap* _inline_get_heap_(); V(Map, neander_map, NeanderMap) \ V(JSObject, message_listeners, MessageListeners) \ V(Foreign, prototype_accessors, PrototypeAccessors) \ - V(NumberDictionary, code_stubs, CodeStubs) \ - V(NumberDictionary, non_monomorphic_cache, NonMonomorphicCache) \ + V(UnseededNumberDictionary, code_stubs, CodeStubs) \ + V(UnseededNumberDictionary, non_monomorphic_cache, NonMonomorphicCache) \ V(PolymorphicCodeCache, polymorphic_code_cache, PolymorphicCodeCache) \ V(Code, js_entry_code, JsEntryCode) \ V(Code, js_construct_entry_code, JsConstructEntryCode) \ @@ -1139,7 +1139,7 @@ class Heap { inline AllocationSpace TargetSpaceId(InstanceType type); // Sets the stub_cache_ (only used when expanding the dictionary). - void public_set_code_stubs(NumberDictionary* value) { + void public_set_code_stubs(UnseededNumberDictionary* value) { roots_[kCodeStubsRootIndex] = value; } @@ -1151,7 +1151,7 @@ class Heap { } // Sets the non_monomorphic_cache_ (only used when expanding the dictionary). - void public_set_non_monomorphic_cache(NumberDictionary* value) { + void public_set_non_monomorphic_cache(UnseededNumberDictionary* value) { roots_[kNonMonomorphicCacheRootIndex] = value; } diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index ad882c054..43f265cf0 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -1064,7 +1064,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, GetNumberHash(r0, r1); // Compute capacity mask. - mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); + mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); shr(r1, kSmiTagSize); // convert smi to int dec(r1); @@ -1075,19 +1075,19 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, mov(r2, r0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - add(r2, Immediate(NumberDictionary::GetProbeOffset(i))); + add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); } and_(r2, r1); // Scale the index by multiplying by the entry size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 // Check if the key matches. cmp(key, FieldOperand(elements, r2, times_pointer_size, - NumberDictionary::kElementsStartOffset)); + SeededNumberDictionary::kElementsStartOffset)); if (i != (kProbes - 1)) { j(equal, &done); } else { @@ -1098,7 +1098,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, bind(&done); // Check that the value is a normal propety. const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; ASSERT_EQ(NORMAL, 0); test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); @@ -1106,7 +1106,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Get the value at the masked, scaled index. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); } diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc index 8fca30505..f6d5a5963 100644 --- a/src/incremental-marking.cc +++ b/src/incremental-marking.cc @@ -418,7 +418,7 @@ void IncrementalMarking::ActivateGeneratedStub(Code* stub) { static void PatchIncrementalMarkingRecordWriteStubs( Heap* heap, RecordWriteStub::Mode mode) { - NumberDictionary* stubs = heap->code_stubs(); + UnseededNumberDictionary* stubs = heap->code_stubs(); int capacity = stubs->Capacity(); for (int i = 0; i < capacity; i++) { diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 87c9ce06e..4517fe181 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -487,7 +487,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, GetNumberHash(reg0, reg1); // Compute the capacity mask. - lw(reg1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); + lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); sra(reg1, reg1, kSmiTagSize); Subu(reg1, reg1, Operand(1)); @@ -498,12 +498,12 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, mov(reg2, reg0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - Addu(reg2, reg2, Operand(NumberDictionary::GetProbeOffset(i))); + Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); } and_(reg2, reg2, reg1); // Scale the index by multiplying by the element size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); sll(at, reg2, 1); // 2x. addu(reg2, reg2, at); // reg2 = reg2 * 3. @@ -511,7 +511,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, sll(at, reg2, kPointerSizeLog2); addu(reg2, elements, at); - lw(at, FieldMemOperand(reg2, NumberDictionary::kElementsStartOffset)); + lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); if (i != kProbes - 1) { Branch(&done, eq, key, Operand(at)); } else { @@ -523,14 +523,14 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Check that the value is a normal property. // reg2: elements + (index * kPointerSize). const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; lw(reg1, FieldMemOperand(reg2, kDetailsOffset)); And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); Branch(miss, ne, at, Operand(zero_reg)); // Get the value at the masked, scaled index and return. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; lw(result, FieldMemOperand(reg2, kValueOffset)); } diff --git a/src/objects-debug.cc b/src/objects-debug.cc index eddfb93be..5c68ddff7 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -746,7 +746,7 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) { break; } case DICTIONARY_ELEMENTS: { - NumberDictionary* dict = element_dictionary(); + SeededNumberDictionary* dict = element_dictionary(); info->number_of_slow_used_elements_ += dict->NumberOfElements(); info->number_of_slow_unused_elements_ += dict->Capacity() - dict->NumberOfElements(); diff --git a/src/objects-inl.h b/src/objects-inl.h index 51e8f3f2f..2e9ccc1fa 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1725,7 +1725,7 @@ void FixedDoubleArray::Initialize(FixedArray* from) { } -void FixedDoubleArray::Initialize(NumberDictionary* from) { +void FixedDoubleArray::Initialize(SeededNumberDictionary* from) { int offset = kHeaderSize; for (int current = 0; current < length(); ++current) { WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double()); @@ -2072,14 +2072,14 @@ int HashTable::FindEntry(Isolate* isolate, Key key) { } -bool NumberDictionary::requires_slow_elements() { +bool SeededNumberDictionary::requires_slow_elements() { Object* max_index_object = get(kMaxNumberKeyIndex); if (!max_index_object->IsSmi()) return false; return 0 != (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask); } -uint32_t NumberDictionary::max_number_key() { +uint32_t SeededNumberDictionary::max_number_key() { ASSERT(!requires_slow_elements()); Object* max_index_object = get(kMaxNumberKeyIndex); if (!max_index_object->IsSmi()) return 0; @@ -2087,7 +2087,7 @@ uint32_t NumberDictionary::max_number_key() { return value >> kRequiresSlowElementsTagSize; } -void NumberDictionary::set_requires_slow_elements() { +void SeededNumberDictionary::set_requires_slow_elements() { set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); } @@ -4299,9 +4299,9 @@ StringDictionary* JSObject::property_dictionary() { } -NumberDictionary* JSObject::element_dictionary() { +SeededNumberDictionary* JSObject::element_dictionary() { ASSERT(HasDictionaryElements()); - return NumberDictionary::cast(elements()); + return SeededNumberDictionary::cast(elements()); } @@ -4538,26 +4538,24 @@ bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { } -uint32_t NumberDictionaryShape::Hash(uint32_t key) { - // This function is unreachable, since shape has UsesSeed=true flag. - UNREACHABLE(); - return 0; +uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) { + return ComputeIntegerHash(key, 0); } -uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { - // This function is unreachable, since shape has UsesSeed=true flag. - UNREACHABLE(); - return 0; +uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key, + Object* other) { + ASSERT(other->IsNumber()); + return ComputeIntegerHash(static_cast(other->Number()), 0); } -uint32_t NumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) { +uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) { return ComputeIntegerHash(key, seed); } -uint32_t NumberDictionaryShape::SeededHashForObject(uint32_t key, - uint32_t seed, - Object* other) { +uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key, + uint32_t seed, + Object* other) { ASSERT(other->IsNumber()); return ComputeIntegerHash(static_cast(other->Number()), seed); } diff --git a/src/objects.cc b/src/objects.cc index f8939660a..abeeec9e2 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -2128,9 +2128,10 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( if (!JSObject::cast(pt)->HasDictionaryElements()) { continue; } - NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); + SeededNumberDictionary* dictionary = + JSObject::cast(pt)->element_dictionary(); int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { *found = true; @@ -3496,9 +3497,11 @@ MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { } -Handle JSObject::NormalizeElements(Handle object) { - CALL_HEAP_FUNCTION( - object->GetIsolate(), object->NormalizeElements(), NumberDictionary); +Handle JSObject::NormalizeElements( + Handle object) { + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->NormalizeElements(), + SeededNumberDictionary); } @@ -3526,11 +3529,11 @@ MaybeObject* JSObject::NormalizeElements() { int old_capacity = 0; int used_elements = 0; GetElementsCapacityAndUsage(&old_capacity, &used_elements); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; { Object* object; - MaybeObject* maybe = NumberDictionary::Allocate(used_elements); + MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements); if (!maybe->ToObject(&object)) return maybe; - dictionary = NumberDictionary::cast(object); + dictionary = SeededNumberDictionary::cast(object); } // Copy the elements to the new backing store. @@ -3561,7 +3564,7 @@ MaybeObject* JSObject::NormalizeElements() { MaybeObject* maybe_result = dictionary->AddNumberEntry(i, value, details); if (!maybe_result->ToObject(&result)) return maybe_result; - dictionary = NumberDictionary::cast(result); + dictionary = SeededNumberDictionary::cast(result); } } @@ -4045,7 +4048,8 @@ bool JSObject::ReferencesObjectFromElements(FixedArray* elements, if (!element->IsTheHole() && element == object) return true; } } else { - Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); + Object* key = + SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); if (!key->IsUndefined()) return true; } return false; @@ -4191,9 +4195,9 @@ MaybeObject* JSObject::PreventExtensions() { } // If there are fast elements we normalize. - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; { MaybeObject* maybe = NormalizeElements(); - if (!maybe->To(&dictionary)) return maybe; + if (!maybe->To(&dictionary)) return maybe; } ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); // Make sure that we never go back to fast case. @@ -4356,12 +4360,13 @@ void JSObject::LookupCallback(String* name, LookupResult* result) { // attributes. Returns either undefined if the element is non-deletable, or the // getter/setter pair if there is an existing one, or the hole value if the // element does not exist or is a normal non-getter/setter data element. -static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary, - uint32_t index, - PropertyAttributes attributes, - Heap* heap) { +static Object* UpdateGetterSetterInDictionary( + SeededNumberDictionary* dictionary, + uint32_t index, + PropertyAttributes attributes, + Heap* heap) { int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* result = dictionary->ValueAt(entry); PropertyDetails details = dictionary->DetailsAt(entry); // TODO(mstarzinger): We should check for details.IsDontDelete() here once @@ -4433,7 +4438,8 @@ MaybeObject* JSObject::DefineGetterSetter(String* name, if (probe == NULL || probe->IsTheHole()) { FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); if (arguments->IsDictionary()) { - NumberDictionary* dictionary = NumberDictionary::cast(arguments); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(arguments); probe = UpdateGetterSetterInDictionary(dictionary, index, attributes, @@ -4505,11 +4511,11 @@ MaybeObject* JSObject::SetElementCallback(uint32_t index, PropertyDetails details = PropertyDetails(attributes, CALLBACKS); // Normalize elements to make this operation simple. - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; { Object* result; MaybeObject* maybe = NormalizeElements(); if (!maybe->ToObject(&result)) return maybe; - dictionary = NumberDictionary::cast(result); + dictionary = SeededNumberDictionary::cast(result); } ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); @@ -4517,7 +4523,7 @@ MaybeObject* JSObject::SetElementCallback(uint32_t index, { Object* result; MaybeObject* maybe = dictionary->Set(index, structure, details); if (!maybe->ToObject(&result)) return maybe; - dictionary = NumberDictionary::cast(result); + dictionary = SeededNumberDictionary::cast(result); } dictionary->set_requires_slow_elements(); @@ -4726,9 +4732,9 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) { obj = JSObject::cast(obj)->GetPrototype()) { JSObject* js_object = JSObject::cast(obj); if (js_object->HasDictionaryElements()) { - NumberDictionary* dictionary = js_object->element_dictionary(); + SeededNumberDictionary* dictionary = js_object->element_dictionary(); int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* element = dictionary->ValueAt(entry); PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { @@ -8266,7 +8272,7 @@ static void CopyFastElementsToFast(FixedArray* source, } -static void CopySlowElementsToFast(NumberDictionary* source, +static void CopySlowElementsToFast(SeededNumberDictionary* source, FixedArray* destination, WriteBarrierMode mode) { int destination_length = destination->length(); @@ -8332,7 +8338,7 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength( case DICTIONARY_ELEMENTS: { AssertNoAllocation no_gc; WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); - CopySlowElementsToFast(NumberDictionary::cast(old_elements_raw), + CopySlowElementsToFast(SeededNumberDictionary::cast(old_elements_raw), new_elements, mode); set_map_and_elements(new_map, new_elements); @@ -8346,7 +8352,7 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength( FixedArray* parameter_map = FixedArray::cast(old_elements_raw); FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); if (arguments->IsDictionary()) { - CopySlowElementsToFast(NumberDictionary::cast(arguments), + CopySlowElementsToFast(SeededNumberDictionary::cast(arguments), new_elements, mode); } else { @@ -8442,7 +8448,7 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( break; } case DICTIONARY_ELEMENTS: { - elems->Initialize(NumberDictionary::cast(old_elements)); + elems->Initialize(SeededNumberDictionary::cast(old_elements)); break; } default: @@ -8702,7 +8708,7 @@ bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { } case DICTIONARY_ELEMENTS: { if (element_dictionary()->FindEntry(index) - != NumberDictionary::kNotFound) { + != SeededNumberDictionary::kNotFound) { return true; } break; @@ -8840,7 +8846,7 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { } case DICTIONARY_ELEMENTS: { if (element_dictionary()->FindEntry(index) != - NumberDictionary::kNotFound) { + SeededNumberDictionary::kNotFound) { return DICTIONARY_ELEMENT; } break; @@ -8857,8 +8863,9 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { // If not aliased, check the arguments. FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); if (arguments->IsDictionary()) { - NumberDictionary* dictionary = NumberDictionary::cast(arguments); - if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) { + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(arguments); + if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) { return DICTIONARY_ELEMENT; } } else { @@ -8887,8 +8894,8 @@ bool JSObject::HasElementInElements(FixedArray* elements, return true; } } else { - if (NumberDictionary::cast(elements)->FindEntry(index) != - NumberDictionary::kNotFound) { + if (SeededNumberDictionary::cast(elements)->FindEntry(index) != + SeededNumberDictionary::kNotFound) { return true; } } @@ -8955,7 +8962,7 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { } case DICTIONARY_ELEMENTS: { if (element_dictionary()->FindEntry(index) - != NumberDictionary::kNotFound) { + != SeededNumberDictionary::kNotFound) { return true; } break; @@ -9278,15 +9285,15 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, FixedArray* elements = FixedArray::cast(this->elements()); bool is_arguments = (elements->map() == heap->non_strict_arguments_elements_map()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (is_arguments) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* element = dictionary->ValueAt(entry); PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { @@ -9331,13 +9338,13 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, FixedArrayBase* new_dictionary; MaybeObject* maybe = dictionary->AtNumberPut(index, value); if (!maybe->To(&new_dictionary)) return maybe; - if (dictionary != NumberDictionary::cast(new_dictionary)) { + if (dictionary != SeededNumberDictionary::cast(new_dictionary)) { if (is_arguments) { elements->set(1, new_dictionary); } else { set_elements(new_dictionary); } - dictionary = NumberDictionary::cast(new_dictionary); + dictionary = SeededNumberDictionary::cast(new_dictionary); } } @@ -9785,7 +9792,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); backing_store = FixedArray::cast(backing_store_base); if (backing_store->IsDictionary()) { - NumberDictionary* dictionary = NumberDictionary::cast(backing_store); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(backing_store); *capacity = dictionary->Capacity(); *used = dictionary->NumberOfElements(); break; @@ -9800,8 +9808,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { } break; case DICTIONARY_ELEMENTS: { - NumberDictionary* dictionary = - NumberDictionary::cast(FixedArray::cast(elements())); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(FixedArray::cast(elements())); *capacity = dictionary->Capacity(); *used = dictionary->NumberOfElements(); break; @@ -9846,8 +9854,8 @@ bool JSObject::ShouldConvertToSlowElements(int new_capacity) { int old_capacity = 0; int used_elements = 0; GetElementsCapacityAndUsage(&old_capacity, &used_elements); - int dictionary_size = NumberDictionary::ComputeCapacity(used_elements) * - NumberDictionary::kEntrySize; + int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * + SeededNumberDictionary::kEntrySize; return 3 * dictionary_size <= new_capacity; } @@ -9861,11 +9869,11 @@ bool JSObject::ShouldConvertToFastElements() { if (IsAccessCheckNeeded()) return false; FixedArray* elements = FixedArray::cast(this->elements()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } // If an element has been added at a very high index in the elements // dictionary, we cannot go back to fast case. @@ -9880,7 +9888,7 @@ bool JSObject::ShouldConvertToFastElements() { array_size = dictionary->max_number_key(); } uint32_t dictionary_size = static_cast(dictionary->Capacity()) * - NumberDictionary::kEntrySize; + SeededNumberDictionary::kEntrySize; return 2 * dictionary_size >= array_size; } @@ -9890,7 +9898,8 @@ bool JSObject::ShouldConvertToFastDoubleElements( *has_smi_only_elements = false; if (FLAG_unbox_double_arrays) { ASSERT(HasDictionaryElements()); - NumberDictionary* dictionary = NumberDictionary::cast(elements()); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(elements()); bool found_double = false; for (int i = 0; i < dictionary->Capacity(); i++) { Object* key = dictionary->KeyAt(i); @@ -10110,7 +10119,7 @@ bool JSObject::HasRealElementProperty(uint32_t index) { } case DICTIONARY_ELEMENTS: { return element_dictionary()->FindEntry(index) - != NumberDictionary::kNotFound; + != SeededNumberDictionary::kNotFound; } case NON_STRICT_ARGUMENTS_ELEMENTS: UNIMPLEMENTED(); @@ -10379,7 +10388,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, if (storage != NULL) { element_dictionary()->CopyKeysTo(storage, filter, - NumberDictionary::SORTED); + SeededNumberDictionary::SORTED); } counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); break; @@ -10391,9 +10400,11 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, if (arguments->IsDictionary()) { // Copy the keys from arguments first, because Dictionary::CopyKeysTo // will insert in storage starting at index 0. - NumberDictionary* dictionary = NumberDictionary::cast(arguments); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(arguments); if (storage != NULL) { - dictionary->CopyKeysTo(storage, filter, NumberDictionary::UNSORTED); + dictionary->CopyKeysTo( + storage, filter, SeededNumberDictionary::UNSORTED); } counter += dictionary->NumberOfElementsFilterAttributes(filter); for (int i = 0; i < mapped_length; ++i) { @@ -11024,38 +11035,46 @@ template class HashTable, Object*>; template class Dictionary; -template class Dictionary; +template class Dictionary; -template MaybeObject* Dictionary::Allocate( - int); +template class Dictionary; + +template MaybeObject* Dictionary:: + Allocate(int at_least_space_for); + +template MaybeObject* Dictionary:: + Allocate(int at_least_space_for); template MaybeObject* Dictionary::Allocate( int); -template MaybeObject* Dictionary::AtPut( +template MaybeObject* Dictionary::AtPut( uint32_t, Object*); -template Object* Dictionary::SlowReverseLookup( - Object*); +template MaybeObject* Dictionary:: + AtPut(uint32_t, Object*); + +template Object* Dictionary:: + SlowReverseLookup(Object* value); template Object* Dictionary::SlowReverseLookup( Object*); -template void Dictionary::CopyKeysTo( +template void Dictionary::CopyKeysTo( FixedArray*, PropertyAttributes, - Dictionary::SortMode); + Dictionary::SortMode); template Object* Dictionary::DeleteProperty( int, JSObject::DeleteMode); -template Object* Dictionary::DeleteProperty( - int, JSObject::DeleteMode); +template Object* Dictionary:: + DeleteProperty(int, JSObject::DeleteMode); template MaybeObject* Dictionary::Shrink( String*); -template MaybeObject* Dictionary::Shrink( +template MaybeObject* Dictionary::Shrink( uint32_t); template void Dictionary::CopyKeysTo( @@ -11074,32 +11093,41 @@ template MaybeObject* Dictionary::GenerateNewEnumerationIndices(); template int -Dictionary::NumberOfElementsFilterAttributes( - PropertyAttributes); +Dictionary:: + NumberOfElementsFilterAttributes(PropertyAttributes); -template MaybeObject* Dictionary::Add( +template MaybeObject* Dictionary::Add( uint32_t, Object*, PropertyDetails); -template MaybeObject* Dictionary:: +template MaybeObject* Dictionary::Add( + uint32_t, Object*, PropertyDetails); + +template MaybeObject* Dictionary:: + EnsureCapacity(int, uint32_t); + +template MaybeObject* Dictionary:: EnsureCapacity(int, uint32_t); template MaybeObject* Dictionary:: EnsureCapacity(int, String*); -template MaybeObject* Dictionary::AddEntry( - uint32_t, Object*, PropertyDetails, uint32_t); +template MaybeObject* Dictionary:: + AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); + +template MaybeObject* Dictionary:: + AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); template MaybeObject* Dictionary::AddEntry( String*, Object*, PropertyDetails, uint32_t); template -int Dictionary::NumberOfEnumElements(); +int Dictionary::NumberOfEnumElements(); template int Dictionary::NumberOfEnumElements(); template -int HashTable::FindEntry(uint32_t); +int HashTable::FindEntry(uint32_t); // Collates undefined and unexisting elements below limit from position @@ -11109,7 +11137,7 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { // Must stay in dictionary mode, either because of requires_slow_elements, // or because we are not going to sort (and therefore compact) all of the // elements. - NumberDictionary* dict = element_dictionary(); + SeededNumberDictionary* dict = element_dictionary(); HeapNumber* result_double = NULL; if (limit > static_cast(Smi::kMaxValue)) { // Allocate space for result before we start mutating the object. @@ -11122,10 +11150,10 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { Object* obj; { MaybeObject* maybe_obj = - NumberDictionary::Allocate(dict->NumberOfElements()); + SeededNumberDictionary::Allocate(dict->NumberOfElements()); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } - NumberDictionary* new_dict = NumberDictionary::cast(obj); + SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj); AssertNoAllocation no_alloc; @@ -11209,7 +11237,7 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { if (HasDictionaryElements()) { // Convert to fast elements containing only the existing properties. // Ordering is irrelevant, since we are going to sort anyway. - NumberDictionary* dict = element_dictionary(); + SeededNumberDictionary* dict = element_dictionary(); if (IsJSArray() || dict->requires_slow_elements() || dict->max_number_key() >= limit) { return PrepareSlowElementsForSort(limit); @@ -12064,7 +12092,7 @@ MaybeObject* Dictionary::AddEntry(Key key, } -void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { +void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { // If the dictionary requires slow elements an element has already // been added at a high index. if (requires_slow_elements()) return; @@ -12083,42 +12111,65 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { } -MaybeObject* NumberDictionary::AddNumberEntry(uint32_t key, - Object* value, - PropertyDetails details) { +MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key, + Object* value, + PropertyDetails details) { UpdateMaxNumberKey(key); SLOW_ASSERT(this->FindEntry(key) == kNotFound); return Add(key, value, details); } -MaybeObject* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { +MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key, + Object* value) { + SLOW_ASSERT(this->FindEntry(key) == kNotFound); + return Add(key, value, PropertyDetails(NONE, NORMAL)); +} + + +MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) { UpdateMaxNumberKey(key); return AtPut(key, value); } -Handle NumberDictionary::Set( - Handle dictionary, +MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key, + Object* value) { + return AtPut(key, value); +} + + +Handle SeededNumberDictionary::Set( + Handle dictionary, uint32_t index, Handle value, PropertyDetails details) { CALL_HEAP_FUNCTION(dictionary->GetIsolate(), dictionary->Set(index, *value, details), - NumberDictionary); + SeededNumberDictionary); } -MaybeObject* NumberDictionary::Set(uint32_t key, - Object* value, - PropertyDetails details) { +Handle UnseededNumberDictionary::Set( + Handle dictionary, + uint32_t index, + Handle value) { + CALL_HEAP_FUNCTION(dictionary->GetIsolate(), + dictionary->Set(index, *value), + UnseededNumberDictionary); +} + + +MaybeObject* SeededNumberDictionary::Set(uint32_t key, + Object* value, + PropertyDetails details) { int entry = FindEntry(key); if (entry == kNotFound) return AddNumberEntry(key, value, details); // Preserve enumeration index. details = PropertyDetails(details.attributes(), details.type(), DetailsAt(entry).index()); - MaybeObject* maybe_object_key = NumberDictionaryShape::AsObject(key); + MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key); Object* object_key; if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; SetEntry(entry, object_key, value, details); @@ -12126,6 +12177,18 @@ MaybeObject* NumberDictionary::Set(uint32_t key, } +MaybeObject* UnseededNumberDictionary::Set(uint32_t key, + Object* value) { + int entry = FindEntry(key); + if (entry == kNotFound) return AddNumberEntry(key, value); + MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key); + Object* object_key; + if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; + SetEntry(entry, object_key, value); + return this; +} + + template int Dictionary::NumberOfElementsFilterAttributes( diff --git a/src/objects.h b/src/objects.h index 2f92d70b3..791aeb364 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1485,7 +1485,7 @@ class JSObject: public JSReceiver { inline bool HasExternalDoubleElements(); bool HasFastArgumentsElements(); bool HasDictionaryArgumentsElements(); - inline NumberDictionary* element_dictionary(); // Gets slow elements. + inline SeededNumberDictionary* element_dictionary(); // Gets slow elements. inline void set_map_and_elements( Map* map, @@ -1908,9 +1908,10 @@ class JSObject: public JSReceiver { PropertyNormalizationMode mode, int expected_additional_properties); - // Convert and update the elements backing store to be a NumberDictionary - // dictionary. Returns the backing after conversion. - static Handle NormalizeElements(Handle object); + // Convert and update the elements backing store to be a + // SeededNumberDictionary dictionary. Returns the backing after conversion. + static Handle NormalizeElements( + Handle object); MUST_USE_RESULT MaybeObject* NormalizeElements(); @@ -2277,7 +2278,7 @@ class FixedDoubleArray: public FixedArrayBase { public: inline void Initialize(FixedArray* from); inline void Initialize(FixedDoubleArray* from); - inline void Initialize(NumberDictionary* from); + inline void Initialize(SeededNumberDictionary* from); // Setter and getter for elements. inline double get_scalar(int index); @@ -3037,28 +3038,41 @@ class StringDictionary: public Dictionary { class NumberDictionaryShape : public BaseShape { + public: + static inline bool IsMatch(uint32_t key, Object* other); + MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key); + static const int kEntrySize = 3; + static const bool kIsEnumerable = false; +}; + + +class SeededNumberDictionaryShape : public NumberDictionaryShape { public: static const bool UsesSeed = true; + static const int kPrefixSize = 2; - static inline bool IsMatch(uint32_t key, Object* other); - static inline uint32_t Hash(uint32_t key); static inline uint32_t SeededHash(uint32_t key, uint32_t seed); - static inline uint32_t HashForObject(uint32_t key, Object* object); static inline uint32_t SeededHashForObject(uint32_t key, uint32_t seed, Object* object); - MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key); - static const int kPrefixSize = 2; - static const int kEntrySize = 3; - static const bool kIsEnumerable = false; }; -class NumberDictionary: public Dictionary { +class UnseededNumberDictionaryShape : public NumberDictionaryShape { + public: + static const int kPrefixSize = 0; + + static inline uint32_t Hash(uint32_t key); + static inline uint32_t HashForObject(uint32_t key, Object* object); +}; + + +class SeededNumberDictionary + : public Dictionary { public: - static NumberDictionary* cast(Object* obj) { + static SeededNumberDictionary* cast(Object* obj) { ASSERT(obj->IsDictionary()); - return reinterpret_cast(obj); + return reinterpret_cast(obj); } // Type specific at put (default NONE attributes is used when adding). @@ -3069,8 +3083,8 @@ class NumberDictionary: public Dictionary { // Set an existing entry or add a new one if needed. // Return the updated dictionary. - MUST_USE_RESULT static Handle Set( - Handle dictionary, + MUST_USE_RESULT static Handle Set( + Handle dictionary, uint32_t index, Handle value, PropertyDetails details); @@ -3101,6 +3115,29 @@ class NumberDictionary: public Dictionary { }; +class UnseededNumberDictionary + : public Dictionary { + public: + static UnseededNumberDictionary* cast(Object* obj) { + ASSERT(obj->IsDictionary()); + return reinterpret_cast(obj); + } + + // Type specific at put (default NONE attributes is used when adding). + MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value); + MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key, Object* value); + + // Set an existing entry or add a new one if needed. + // Return the updated dictionary. + MUST_USE_RESULT static Handle Set( + Handle dictionary, + uint32_t index, + Handle value); + + MUST_USE_RESULT MaybeObject* Set(uint32_t key, Object* value); +}; + + template class ObjectHashTableShape : public BaseShape { public: diff --git a/src/profile-generator.cc b/src/profile-generator.cc index 852e28ddb..97de08e5b 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -1231,10 +1231,10 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, entries_sorted_(false) { STATIC_ASSERT( sizeof(HeapGraphEdge) == - SnapshotSizeConstants::kExpectedHeapGraphEdgeSize); // NOLINT + SnapshotSizeConstants::kExpectedHeapGraphEdgeSize); STATIC_ASSERT( sizeof(HeapEntry) == - SnapshotSizeConstants::kExpectedHeapEntrySize); // NOLINT + SnapshotSizeConstants::kExpectedHeapEntrySize); for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { gc_subroot_entries_[i] = NULL; } @@ -2289,7 +2289,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, } } } else if (js_obj->HasDictionaryElements()) { - NumberDictionary* dictionary = js_obj->element_dictionary(); + SeededNumberDictionary* dictionary = js_obj->element_dictionary(); int length = dictionary->Capacity(); for (int i = 0; i < length; ++i) { Object* k = dictionary->KeyAt(i); diff --git a/src/runtime.cc b/src/runtime.cc index df37174c5..fb3621341 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -228,7 +228,7 @@ MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, break; } case DICTIONARY_ELEMENTS: { - NumberDictionary* element_dictionary = copy->element_dictionary(); + SeededNumberDictionary* element_dictionary = copy->element_dictionary(); int capacity = element_dictionary->Capacity(); for (int i = 0; i < capacity; i++) { Object* k = element_dictionary->KeyAt(i); @@ -1044,14 +1044,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) { holder = Handle(JSObject::cast(proto)); } FixedArray* elements = FixedArray::cast(holder->elements()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (elements->map() == heap->non_strict_arguments_elements_map()) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } int entry = dictionary->FindEntry(index); - ASSERT(entry != NumberDictionary::kNotFound); + ASSERT(entry != SeededNumberDictionary::kNotFound); PropertyDetails details = dictionary->DetailsAt(entry); switch (details.type()) { case CALLBACKS: { @@ -4300,13 +4300,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { return isolate->Throw(*error); } - Handle dictionary = + Handle dictionary = JSObject::NormalizeElements(js_object); // Make sure that we never go back to fast case. dictionary->set_requires_slow_elements(); PropertyDetails details = PropertyDetails(attr, NORMAL); - Handle extended_dictionary = - NumberDictionary::Set(dictionary, index, obj_value, details); + Handle extended_dictionary = + SeededNumberDictionary::Set(dictionary, index, obj_value, details); if (*extended_dictionary != *dictionary) { if (js_object->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) { FixedArray::cast(js_object->elements())->set(1, *extended_dictionary); @@ -4381,12 +4381,13 @@ static MaybeObject* NormalizeObjectSetElement(Isolate* isolate, Handle value, PropertyAttributes attr) { // Normalize the elements to enable attributes on the property. - Handle dictionary = JSObject::NormalizeElements(js_object); + Handle dictionary = + JSObject::NormalizeElements(js_object); // Make sure that we never go back to fast case. dictionary->set_requires_slow_elements(); PropertyDetails details = PropertyDetails(attr, NORMAL); - Handle extended_dictionary = - NumberDictionary::Set(dictionary, index, value, details); + Handle extended_dictionary = + SeededNumberDictionary::Set(dictionary, index, value, details); if (*extended_dictionary != *dictionary) { js_object->set_elements(*extended_dictionary); } @@ -4815,15 +4816,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { object = JSObject::cast(proto); } FixedArray* elements = FixedArray::cast(object->elements()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (elements->map() == isolate->heap()->non_strict_arguments_elements_map()) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } int entry = dictionary->FindEntry(index); - ASSERT(entry != NumberDictionary::kNotFound); + ASSERT(entry != SeededNumberDictionary::kNotFound); PropertyDetails details = dictionary->DetailsAt(entry); return isolate->heap()->ToBoolean(!details.IsDontEnum()); } @@ -9582,8 +9583,9 @@ class ArrayConcatVisitor { // Fall-through to dictionary mode. } ASSERT(!fast_elements_); - Handle dict(NumberDictionary::cast(*storage_)); - Handle result = + Handle dict( + SeededNumberDictionary::cast(*storage_)); + Handle result = isolate_->factory()->DictionaryAtNumberPut(dict, index, elm); if (!result.is_identical_to(dict)) { // Dictionary needed to grow. @@ -9623,14 +9625,15 @@ class ArrayConcatVisitor { void SetDictionaryMode(uint32_t index) { ASSERT(fast_elements_); Handle current_storage(*storage_); - Handle slow_storage( - isolate_->factory()->NewNumberDictionary(current_storage->length())); + Handle slow_storage( + isolate_->factory()->NewSeededNumberDictionary( + current_storage->length())); uint32_t current_length = static_cast(current_storage->length()); for (uint32_t i = 0; i < current_length; i++) { HandleScope loop_scope; Handle element(current_storage->get(i)); if (!element->IsTheHole()) { - Handle new_storage = + Handle new_storage = isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element); if (!new_storage.is_identical_to(slow_storage)) { slow_storage = loop_scope.CloseAndEscape(new_storage); @@ -9682,8 +9685,8 @@ static uint32_t EstimateElementCount(Handle array) { UNREACHABLE(); break; case DICTIONARY_ELEMENTS: { - Handle dictionary( - NumberDictionary::cast(array->elements())); + Handle dictionary( + SeededNumberDictionary::cast(array->elements())); int capacity = dictionary->Capacity(); for (int i = 0; i < capacity; i++) { Handle key(dictionary->KeyAt(i)); @@ -9786,7 +9789,8 @@ static void CollectElementIndices(Handle object, break; } case DICTIONARY_ELEMENTS: { - Handle dict(NumberDictionary::cast(object->elements())); + Handle dict( + SeededNumberDictionary::cast(object->elements())); uint32_t capacity = dict->Capacity(); for (uint32_t j = 0; j < capacity; j++) { HandleScope loop_scope; @@ -9921,7 +9925,7 @@ static bool IterateElements(Isolate* isolate, break; } case DICTIONARY_ELEMENTS: { - Handle dict(receiver->element_dictionary()); + Handle dict(receiver->element_dictionary()); List indices(dict->Capacity() / 2); // Collect all indices in the object and the prototypes less // than length. This might introduce duplicates in the indices list. @@ -10077,7 +10081,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { uint32_t at_least_space_for = estimate_nof_elements + (estimate_nof_elements >> 2); storage = Handle::cast( - isolate->factory()->NewNumberDictionary(at_least_space_for)); + isolate->factory()->NewSeededNumberDictionary(at_least_space_for)); } ArrayConcatVisitor visitor(isolate, storage, fast_case); @@ -10165,7 +10169,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) { CONVERT_CHECKED(JSObject, object, args[0]); HeapObject* elements = object->elements(); if (elements->IsDictionary()) { - return Smi::FromInt(NumberDictionary::cast(elements)->NumberOfElements()); + int result = SeededNumberDictionary::cast(elements)->NumberOfElements(); + return Smi::FromInt(result); } else if (object->IsJSArray()) { return JSArray::cast(object)->length(); } else { diff --git a/src/stub-cache.cc b/src/stub-cache.cc index 91ffa7194..ec8f6bdf2 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -678,11 +678,10 @@ Handle StubCache::ComputeCallGlobal(int argc, static void FillCache(Isolate* isolate, Handle code) { - Handle dictionary = - NumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), - code->flags(), - code, - PropertyDetails(NONE, NORMAL)); + Handle dictionary = + UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), + code->flags(), + code); isolate->heap()->public_set_non_monomorphic_cache(*dictionary); } @@ -697,7 +696,7 @@ Code* StubCache::FindCallInitialize(int argc, Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc); // Use raw_unchecked... so we don't get assert failures during GC. - NumberDictionary* dictionary = + UnseededNumberDictionary* dictionary = isolate()->heap()->raw_unchecked_non_monomorphic_cache(); int entry = dictionary->FindEntry(isolate(), flags); ASSERT(entry != -1); @@ -716,7 +715,8 @@ Handle StubCache::ComputeCallInitialize(int argc, CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); Code::Flags flags = Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -744,7 +744,8 @@ Handle StubCache::ComputeCallPreMonomorphic( Code::ExtraICState extra_state) { Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -760,7 +761,8 @@ Handle StubCache::ComputeCallNormal(int argc, Code::ExtraICState extra_state) { Code::Flags flags = Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -776,7 +778,8 @@ Handle StubCache::ComputeCallArguments(int argc, Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -794,7 +797,8 @@ Handle StubCache::ComputeCallMegamorphic( Code::Flags flags = Code::ComputeFlags(kind, MEGAMORPHIC, extra_state, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -813,7 +817,8 @@ Handle StubCache::ComputeCallMiss(int argc, Code::Flags flags = Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, NORMAL, argc, OWN_MAP); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -832,7 +837,8 @@ Handle StubCache::ComputeCallDebugBreak(int argc, Code::Flags flags = Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); @@ -850,7 +856,8 @@ Handle StubCache::ComputeCallDebugPrepareStepIn(int argc, Code::Flags flags = Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState, NORMAL, argc); - Handle cache = isolate_->factory()->non_monomorphic_cache(); + Handle cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle(Code::cast(cache->ValueAt(entry))); diff --git a/src/type-info.cc b/src/type-info.cc index 790d77cb1..fcdc6108f 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -71,7 +71,7 @@ TypeFeedbackOracle::TypeFeedbackOracle(Handle code, Handle TypeFeedbackOracle::GetInfo(unsigned ast_id) { int entry = dictionary_->FindEntry(ast_id); - return entry != NumberDictionary::kNotFound + return entry != UnseededNumberDictionary::kNotFound ? Handle(dictionary_->ValueAt(entry)) : Handle::cast(isolate_->factory()->undefined_value()); } @@ -559,7 +559,7 @@ void TypeFeedbackOracle::CreateDictionary(Handle code, ZoneList* infos) { DisableAssertNoAllocation allocation_allowed; byte* old_start = code->instruction_start(); - dictionary_ = FACTORY->NewNumberDictionary(infos->length()); + dictionary_ = FACTORY->NewUnseededNumberDictionary(infos->length()); byte* new_start = code->instruction_start(); RelocateRelocInfos(infos, old_start, new_start); } @@ -639,7 +639,7 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList* infos) { void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { - ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); + ASSERT(dictionary_->FindEntry(ast_id) == UnseededNumberDictionary::kNotFound); MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); USE(maybe_result); #ifdef DEBUG diff --git a/src/type-info.h b/src/type-info.h index 1519fcabb..9d3080abb 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -303,7 +303,7 @@ class TypeFeedbackOracle BASE_EMBEDDED { Handle global_context_; Isolate* isolate_; - Handle dictionary_; + Handle dictionary_; DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle); }; diff --git a/src/v8globals.h b/src/v8globals.h index 005cdbdae..bdb960e8f 100644 --- a/src/v8globals.h +++ b/src/v8globals.h @@ -130,7 +130,8 @@ class FixedArray; class FunctionLiteral; class FunctionTemplateInfo; class MemoryChunk; -class NumberDictionary; +class SeededNumberDictionary; +class UnseededNumberDictionary; class StringDictionary; template class Handle; class Heap; diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 9c12731e9..47553697a 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -3488,8 +3488,8 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, GetNumberHash(r0, r1); // Compute capacity mask. - SmiToInteger32(r1, - FieldOperand(elements, NumberDictionary::kCapacityOffset)); + SmiToInteger32(r1, FieldOperand(elements, + SeededNumberDictionary::kCapacityOffset)); decl(r1); // Generate an unrolled loop that performs a few probes before giving up. @@ -3499,19 +3499,19 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, movq(r2, r0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - addl(r2, Immediate(NumberDictionary::GetProbeOffset(i))); + addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); } and_(r2, r1); // Scale the index by multiplying by the entry size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 // Check if the key matches. cmpq(key, FieldOperand(elements, r2, times_pointer_size, - NumberDictionary::kElementsStartOffset)); + SeededNumberDictionary::kElementsStartOffset)); if (i != (kProbes - 1)) { j(equal, &done); } else { @@ -3522,7 +3522,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, bind(&done); // Check that the value is a normal propety. const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; ASSERT_EQ(NORMAL, 0); Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), Smi::FromInt(PropertyDetails::TypeField::kMask)); @@ -3530,7 +3530,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Get the value at the masked, scaled index. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); } -- 2.34.1