From 72424b3987294b2db2131b6960e2b035dffcffe7 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Wed, 17 Oct 2012 13:04:49 +0000 Subject: [PATCH] Move DescriptorArray into the map. Review URL: https://chromiumcodereview.appspot.com/11188031 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12746 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/macro-assembler-arm.cc | 24 +---- src/bootstrapper.cc | 18 ++-- src/heap-inl.h | 7 -- src/heap.cc | 13 +-- src/ia32/macro-assembler-ia32.cc | 23 +---- src/mips/macro-assembler-mips.cc | 24 +---- src/objects-inl.h | 55 ++-------- src/objects-printer.cc | 5 +- src/objects-visiting-inl.h | 8 -- src/objects.cc | 162 +++++++++--------------------- src/objects.h | 24 ++--- src/profile-generator.cc | 11 +- src/spaces.h | 5 +- src/transitions-inl.h | 17 ---- src/transitions.cc | 10 -- src/transitions.h | 49 +++++---- src/v8globals.h | 13 --- src/x64/macro-assembler-x64.cc | 23 +---- test/cctest/test-alloc.cc | 2 +- test/cctest/test-heap-profiler.cc | 12 +-- 20 files changed, 121 insertions(+), 384 deletions(-) diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 31915a519..4409e2643 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -3742,29 +3742,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg, void MacroAssembler::LoadInstanceDescriptors(Register map, Register descriptors, Register scratch) { - Register temp = descriptors; - ldr(temp, FieldMemOperand(map, Map::kTransitionsOrBackPointerOffset)); - - Label ok, fail, load_from_back_pointer; - CheckMap(temp, - scratch, - isolate()->factory()->fixed_array_map(), - &fail, - DONT_DO_SMI_CHECK); - ldr(descriptors, FieldMemOperand(temp, TransitionArray::kDescriptorsOffset)); - jmp(&ok); - - bind(&fail); - CompareRoot(temp, Heap::kUndefinedValueRootIndex); - b(ne, &load_from_back_pointer); - mov(descriptors, Operand(FACTORY->empty_descriptor_array())); - jmp(&ok); - - bind(&load_from_back_pointer); - ldr(temp, FieldMemOperand(temp, Map::kTransitionsOrBackPointerOffset)); - ldr(descriptors, FieldMemOperand(temp, TransitionArray::kDescriptorsOffset)); - - bind(&ok); + ldr(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); } diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 4b40d92c3..a368eefe7 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -397,7 +397,7 @@ void Genesis::SetFunctionInstanceDescriptor( } PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE | READ_ONLY); - Map::SetDescriptors(map, descriptors); + map->set_instance_descriptors(*descriptors); { // Add length. CallbacksDescriptor d(*factory()->length_symbol(), *length, attribs); @@ -538,7 +538,7 @@ void Genesis::SetStrictFunctionInstanceDescriptor( } PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE); - Map::SetDescriptors(map, descriptors); + map->set_instance_descriptors(*descriptors); { // Add length. CallbacksDescriptor d(*factory()->length_symbol(), *length, attribs); @@ -875,7 +875,7 @@ bool Genesis::InitializeGlobal(Handle inner_global, Handle array_length(factory->NewForeign(&Accessors::ArrayLength)); PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE); - Map::SetDescriptors(initial_map, array_descriptors); + initial_map->set_instance_descriptors(*array_descriptors); { // Add length. CallbacksDescriptor d(*factory->length_symbol(), *array_length, attribs); @@ -924,7 +924,7 @@ bool Genesis::InitializeGlobal(Handle inner_global, factory->NewForeign(&Accessors::StringLength)); PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE | READ_ONLY); - Map::SetDescriptors(string_map, string_descriptors); + string_map->set_instance_descriptors(*string_descriptors); { // Add length. CallbacksDescriptor d(*factory->length_symbol(), *string_length, attribs); @@ -960,7 +960,7 @@ bool Genesis::InitializeGlobal(Handle inner_global, static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); Handle descriptors = factory->NewDescriptorArray(0, 5); DescriptorArray::WhitenessWitness witness(*descriptors); - Map::SetDescriptors(initial_map, descriptors); + initial_map->set_instance_descriptors(*descriptors); { // ECMA-262, section 15.10.7.1. @@ -1144,7 +1144,7 @@ bool Genesis::InitializeGlobal(Handle inner_global, // Create the descriptor array for the arguments object. Handle descriptors = factory->NewDescriptorArray(0, 3); DescriptorArray::WhitenessWitness witness(*descriptors); - Map::SetDescriptors(map, descriptors); + map->set_instance_descriptors(*descriptors); { // length FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM); @@ -1534,7 +1534,7 @@ bool Genesis::InstallNatives() { factory()->NewForeign(&Accessors::ScriptEvalFromFunctionName)); PropertyAttributes attribs = static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); - Map::SetDescriptors(script_map, script_descriptors); + script_map->set_instance_descriptors(*script_descriptors); { CallbacksDescriptor d( @@ -1675,7 +1675,7 @@ bool Genesis::InstallNatives() { &Accessors::ArrayLength)); PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE); - Map::SetDescriptors(initial_map, array_descriptors); + initial_map->set_instance_descriptors(*array_descriptors); { // Add length. CallbacksDescriptor d( @@ -1770,7 +1770,7 @@ bool Genesis::InstallNatives() { Handle reresult_descriptors = factory()->NewDescriptorArray(0, 3); DescriptorArray::WhitenessWitness witness(*reresult_descriptors); - Map::SetDescriptors(initial_map, reresult_descriptors); + initial_map->set_instance_descriptors(*reresult_descriptors); { JSFunction* array_function = native_context()->array_function(); diff --git a/src/heap-inl.h b/src/heap-inl.h index 876d8d833..a7645e25f 100644 --- a/src/heap-inl.h +++ b/src/heap-inl.h @@ -267,13 +267,6 @@ MaybeObject* Heap::AllocateRawMap() { #endif MaybeObject* result = map_space_->AllocateRaw(Map::kSize); if (result->IsFailure()) old_gen_exhausted_ = true; -#ifdef DEBUG - if (!result->IsFailure()) { - // Maps have their own alignment. - CHECK((reinterpret_cast(result) & kMapAlignmentMask) == - static_cast(kHeapObjectTag)); - } -#endif return result; } diff --git a/src/heap.cc b/src/heap.cc index 5de06aa60..4fd1a041e 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -2102,6 +2102,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type, map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER); map->init_back_pointer(undefined_value()); map->set_unused_property_fields(0); + map->set_instance_descriptors(empty_descriptor_array()); map->set_bit_field(0); map->set_bit_field2(1 << Map::kIsExtensible); int bit_field3 = Map::EnumLengthBits::encode(Map::kInvalidEnumCache) | @@ -2109,12 +2110,6 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type, map->set_bit_field3(bit_field3); map->set_elements_kind(elements_kind); - // If the map object is aligned fill the padding area with Smi 0 objects. - if (Map::kPadStart < Map::kSize) { - memset(reinterpret_cast(map) + Map::kPadStart - kHeapObjectTag, - 0, - Map::kSize - Map::kPadStart); - } return map; } @@ -2241,12 +2236,15 @@ bool Heap::CreateInitialMaps() { // Fix the instance_descriptors for the existing maps. meta_map()->set_code_cache(empty_fixed_array()); meta_map()->init_back_pointer(undefined_value()); + meta_map()->set_instance_descriptors(empty_descriptor_array()); fixed_array_map()->set_code_cache(empty_fixed_array()); fixed_array_map()->init_back_pointer(undefined_value()); + fixed_array_map()->set_instance_descriptors(empty_descriptor_array()); oddball_map()->set_code_cache(empty_fixed_array()); oddball_map()->init_back_pointer(undefined_value()); + oddball_map()->set_instance_descriptors(empty_descriptor_array()); // Fix prototype object for existing maps. meta_map()->set_prototype(null_value()); @@ -3956,8 +3954,7 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) { if (HasDuplicates(descriptors)) { fun->shared()->ForbidInlineConstructor(); } else { - MaybeObject* maybe_failure = map->InitializeDescriptors(descriptors); - if (maybe_failure->IsFailure()) return maybe_failure; + map->InitializeDescriptors(descriptors); map->set_pre_allocated_property_fields(count); map->set_unused_property_fields(in_object_properties - count); } diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 1a64c4536..c17a466d4 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -2577,28 +2577,7 @@ void MacroAssembler::Abort(const char* msg) { void MacroAssembler::LoadInstanceDescriptors(Register map, Register descriptors) { - Register temp = descriptors; - mov(temp, FieldOperand(map, Map::kTransitionsOrBackPointerOffset)); - - Label ok, fail, load_from_back_pointer; - CheckMap(temp, - isolate()->factory()->fixed_array_map(), - &fail, - DONT_DO_SMI_CHECK); - mov(descriptors, FieldOperand(temp, TransitionArray::kDescriptorsOffset)); - jmp(&ok); - - bind(&fail); - cmp(temp, isolate()->factory()->undefined_value()); - j(not_equal, &load_from_back_pointer, Label::kNear); - mov(descriptors, isolate()->factory()->empty_descriptor_array()); - jmp(&ok); - - bind(&load_from_back_pointer); - mov(temp, FieldOperand(temp, Map::kTransitionsOrBackPointerOffset)); - mov(descriptors, FieldOperand(temp, TransitionArray::kDescriptorsOffset)); - - bind(&ok); + mov(descriptors, FieldOperand(map, Map::kDescriptorsOffset)); } diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 489eeb05f..dacfc0ed5 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -5304,29 +5304,7 @@ void MacroAssembler::EnsureNotWhite( void MacroAssembler::LoadInstanceDescriptors(Register map, Register descriptors, Register scratch) { - Register temp = descriptors; - lw(temp, FieldMemOperand(map, Map::kTransitionsOrBackPointerOffset)); - - Label ok, fail, load_from_back_pointer; - CheckMap(temp, - scratch, - isolate()->factory()->fixed_array_map(), - &fail, - DONT_DO_SMI_CHECK); - lw(descriptors, FieldMemOperand(temp, TransitionArray::kDescriptorsOffset)); - jmp(&ok); - - bind(&fail); - LoadRoot(scratch, Heap::kUndefinedValueRootIndex); - Branch(&load_from_back_pointer, ne, temp, Operand(scratch)); - LoadRoot(descriptors, Heap::kEmptyDescriptorArrayRootIndex); - jmp(&ok); - - bind(&load_from_back_pointer); - lw(temp, FieldMemOperand(temp, Map::kTransitionsOrBackPointerOffset)); - lw(descriptors, FieldMemOperand(temp, TransitionArray::kDescriptorsOffset)); - - bind(&ok); + lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); } diff --git a/src/objects-inl.h b/src/objects-inl.h index 7e0ba9f10..e769c15e8 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -3548,32 +3548,16 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) { } -DescriptorArray* Map::instance_descriptors() { - if (HasTransitionArray()) return transitions()->descriptors(); - Object* back_pointer = GetBackPointer(); - if (!back_pointer->IsMap()) return GetHeap()->empty_descriptor_array(); - return Map::cast(back_pointer)->instance_descriptors(); -} - - -enum TransitionsKind { DESCRIPTORS_HOLDER, FULL_TRANSITION_ARRAY }; - - // If the descriptor is using the empty transition array, install a new empty // transition array that will have place for an element transition. -static MaybeObject* EnsureHasTransitionArray(Map* map, TransitionsKind kind) { +static MaybeObject* EnsureHasTransitionArray(Map* map) { TransitionArray* transitions; MaybeObject* maybe_transitions; if (!map->HasTransitionArray()) { - if (kind == FULL_TRANSITION_ARRAY) { - maybe_transitions = TransitionArray::Allocate(0); - } else { - maybe_transitions = TransitionArray::AllocateDescriptorsHolder(); - } + maybe_transitions = TransitionArray::Allocate(0); if (!maybe_transitions->To(&transitions)) return maybe_transitions; transitions->set_back_pointer_storage(map->GetBackPointer()); - } else if (kind == FULL_TRANSITION_ARRAY && - !map->transitions()->IsFullTransitionArray()) { + } else if (!map->transitions()->IsFullTransitionArray()) { maybe_transitions = map->transitions()->ExtendToFullTransitionArray(); if (!maybe_transitions->To(&transitions)) return maybe_transitions; } else { @@ -3584,19 +3568,7 @@ static MaybeObject* EnsureHasTransitionArray(Map* map, TransitionsKind kind) { } -MaybeObject* Map::SetDescriptors(DescriptorArray* value) { - ASSERT(!is_shared()); - MaybeObject* maybe_failure = - EnsureHasTransitionArray(this, DESCRIPTORS_HOLDER); - if (maybe_failure->IsFailure()) return maybe_failure; - - ASSERT(NumberOfOwnDescriptors() <= value->number_of_descriptors()); - transitions()->set_descriptors(value); - return this; -} - - -MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) { +void Map::InitializeDescriptors(DescriptorArray* descriptors) { int len = descriptors->number_of_descriptors(); #ifdef DEBUG ASSERT(len <= DescriptorArray::kMaxNumberOfDescriptors); @@ -3615,14 +3587,12 @@ MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) { } #endif - MaybeObject* maybe_failure = SetDescriptors(descriptors); - if (maybe_failure->IsFailure()) return maybe_failure; - + set_instance_descriptors(descriptors); SetNumberOfOwnDescriptors(len); - return this; } +ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset) SMI_ACCESSORS(Map, bit_field3, kBitField3Offset) @@ -3688,8 +3658,7 @@ MaybeObject* Map::AddTransition(String* key, Map* target, SimpleTransitionFlag flag) { if (HasTransitionArray()) return transitions()->CopyInsert(key, target); - return TransitionArray::NewWith( - flag, key, target, instance_descriptors(), GetBackPointer()); + return TransitionArray::NewWith(flag, key, target, GetBackPointer()); } @@ -3704,11 +3673,8 @@ Map* Map::GetTransition(int transition_index) { MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) { - DescriptorArray* descriptors = instance_descriptors(); - MaybeObject* allow_elements = - EnsureHasTransitionArray(this, FULL_TRANSITION_ARRAY); + MaybeObject* allow_elements = EnsureHasTransitionArray(this); if (allow_elements->IsFailure()) return allow_elements; - transitions()->set_descriptors(descriptors); transitions()->set_elements_transition(transitioned_map); return this; } @@ -3724,9 +3690,7 @@ FixedArray* Map::GetPrototypeTransitions() { MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { - DescriptorArray* descriptors = instance_descriptors(); - MaybeObject* allow_prototype = - EnsureHasTransitionArray(this, FULL_TRANSITION_ARRAY); + MaybeObject* allow_prototype = EnsureHasTransitionArray(this); if (allow_prototype->IsFailure()) return allow_prototype; #ifdef DEBUG if (HasPrototypeTransitions()) { @@ -3734,7 +3698,6 @@ MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { ZapPrototypeTransitions(); } #endif - transitions()->set_descriptors(descriptors); transitions()->SetPrototypeTransitions(proto_transitions); return this; } diff --git a/src/objects-printer.cc b/src/objects-printer.cc index d7727c1e9..b1118de9c 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -564,10 +564,9 @@ void Map::MapPrint(FILE* out) { } PrintF(out, " - back pointer: "); GetBackPointer()->ShortPrint(out); - PrintF(out, "\n - instance descriptors %i #%i %i: ", + PrintF(out, "\n - instance descriptors %i #%i: ", owns_descriptors(), - NumberOfOwnDescriptors(), - StoresOwnDescriptors()); + NumberOfOwnDescriptors()); instance_descriptors()->ShortPrint(out); if (HasTransitionArray()) { PrintF(out, "\n - transitions: "); diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h index b704c1f37..d698a8df0 100644 --- a/src/objects-visiting-inl.h +++ b/src/objects-visiting-inl.h @@ -390,14 +390,6 @@ void StaticMarkingVisitor::MarkTransitionArray( Heap* heap, TransitionArray* transitions) { if (!StaticVisitor::MarkObjectWithoutPush(heap, transitions)) return; - // Skip recording the descriptors_pointer slot since the cell space - // is not compacted and descriptors are referenced through a cell. - Object** descriptors_slot = transitions->GetDescriptorsSlot(); - HeapObject* descriptors = HeapObject::cast(*descriptors_slot); - StaticVisitor::MarkObject(heap, descriptors); - heap->mark_compact_collector()->RecordSlot( - descriptors_slot, descriptors_slot, descriptors); - // Simple transitions do not have keys nor prototype transitions. if (transitions->IsSimpleTransition()) return; diff --git a/src/objects.cc b/src/objects.cc index 250e009b2..c9e34d587 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1764,23 +1764,6 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition( Map* old_target = old_map->GetTransition(transition_index); Object* result; - // To sever a transition to a map with which the descriptors are shared, the - // larger map (more descriptors) needs to store its own descriptors array. - // Both sides of the severed chain need to have their own descriptors pointer - // to store distinct descriptor arrays. - - // If the old_target did not yet store its own descriptors, the new - // descriptors pointer is created for the old_target by temporarily clearing - // the back pointer and setting its descriptor array. - - // This phase is executed before creating the new map since it requires - // allocation that may fail. - if (!old_target->StoresOwnDescriptors()) { - DescriptorArray* old_descriptors = old_map->instance_descriptors(); - MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); - if (maybe_failure->IsFailure()) return maybe_failure; - } - MaybeObject* maybe_result = ConvertDescriptorToField(name, new_value, attributes); if (!maybe_result->To(&result)) return maybe_result; @@ -1801,8 +1784,7 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition( old_target->instance_descriptors() == old_map->instance_descriptors()) { // Since the conversion above generated a new fast map with an additional // property which can be shared as well, install this descriptor pointer - // along the entire chain of smaller maps; and remove the transition array - // that is only in place to hold the descriptor array in the new map. + // along the entire chain of smaller maps. Map* map; DescriptorArray* new_descriptors = new_map->instance_descriptors(); DescriptorArray* old_descriptors = old_map->instance_descriptors(); @@ -1810,14 +1792,11 @@ MaybeObject* JSObject::ConvertTransitionToMapTransition( !current->IsUndefined(); current = map->GetBackPointer()) { map = Map::cast(current); - if (!map->HasTransitionArray()) break; - TransitionArray* transitions = map->transitions(); - if (transitions->descriptors() != old_descriptors) break; + if (map->instance_descriptors() != old_descriptors) break; map->SetEnumLength(Map::kInvalidEnumCache); - transitions->set_descriptors(new_descriptors); + map->set_instance_descriptors(new_descriptors); } old_map->set_owns_descriptors(false); - new_map->ClearTransitions(GetHeap()); } old_map->SetTransition(transition_index, new_map); @@ -2201,7 +2180,7 @@ void Map::EnsureDescriptorSlack(Handle map, int slack) { new_descriptors->CopyFrom(i, *descriptors, i, witness); } - Map::SetDescriptors(map, new_descriptors); + map->set_instance_descriptors(*new_descriptors); } @@ -4229,13 +4208,6 @@ bool JSReceiver::IsSimpleEnum() { } -void Map::SetDescriptors(Handle map, - Handle descriptors) { - Isolate* isolate = map->GetIsolate(); - CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); -} - - int Map::NumberOfDescribedProperties(DescriptorFlag which, PropertyAttributes filter) { int result = 0; @@ -5013,37 +4985,37 @@ MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors, new_descriptors->Append(descriptor, witness); - // If the source descriptors had an enum cache we copy it. This ensures that - // the maps to which we push the new descriptor array back can rely on a - // cache always being available once it is set. If the map has more - // enumerated descriptors than available in the original cache, the cache - // will be lazily replaced by the extended cache when needed. - if (descriptors->HasEnumCache()) { - new_descriptors->CopyEnumCacheFrom(descriptors); - } + if (old_size > 0) { + // If the source descriptors had an enum cache we copy it. This ensures + // that the maps to which we push the new descriptor array back can rely + // on a cache always being available once it is set. If the map has more + // enumerated descriptors than available in the original cache, the cache + // will be lazily replaced by the extended cache when needed. + if (descriptors->HasEnumCache()) { + new_descriptors->CopyEnumCacheFrom(descriptors); + } - Map* map; - // Replace descriptors by new_descriptors in all maps that share it. - for (Object* current = GetBackPointer(); - !current->IsUndefined(); - current = map->GetBackPointer()) { - map = Map::cast(current); - if (!map->HasTransitionArray()) break; - TransitionArray* transitions = map->transitions(); - if (transitions->descriptors() != descriptors) break; - transitions->set_descriptors(new_descriptors); - } + Map* map; + // Replace descriptors by new_descriptors in all maps that share it. + for (Object* current = GetBackPointer(); + !current->IsUndefined(); + current = map->GetBackPointer()) { + map = Map::cast(current); + if (map->instance_descriptors() != descriptors) break; + map->set_instance_descriptors(new_descriptors); + } - transitions->set_descriptors(new_descriptors); + set_instance_descriptors(new_descriptors); + } } - set_transitions(transitions); result->SetBackPointer(this); - set_owns_descriptors(false); - - result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); + result->InitializeDescriptors(new_descriptors); ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); + set_transitions(transitions); + set_owns_descriptors(false); + return result; } @@ -5058,13 +5030,7 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, MaybeObject* maybe_result = CopyDropDescriptors(); if (!maybe_result->To(&result)) return maybe_result; - // Unless we are creating a map with no descriptors and no back pointer, we - // insert the descriptor array locally. - if (!descriptors->IsEmpty()) { - MaybeObject* maybe_failure = result->SetDescriptors(descriptors); - if (maybe_failure->IsFailure()) return maybe_failure; - result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); - } + result->InitializeDescriptors(descriptors); if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { TransitionArray* transitions; @@ -5075,23 +5041,6 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); if (!maybe_transitions->To(&transitions)) return maybe_transitions; - if (descriptors->IsEmpty()) { - if (owns_descriptors()) { - // If the copied map has no added fields, and the parent map owns its - // descriptors, those descriptors have to be empty. In that case, - // transfer ownership of the descriptors to the new child. - ASSERT(instance_descriptors()->IsEmpty()); - set_owns_descriptors(false); - } else { - // If the parent did not own its own descriptors, it may share a larger - // descriptors array already. In that case, force a split by setting - // the descriptor array of the new map to the empty descriptor array. - MaybeObject* maybe_failure = - result->SetDescriptors(GetHeap()->empty_descriptor_array()); - if (maybe_failure->IsFailure()) return maybe_failure; - } - } - set_transitions(transitions); result->SetBackPointer(this); } @@ -5113,7 +5062,10 @@ MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { ASSERT(kind != elements_kind()); } - if (flag == INSERT_TRANSITION && owns_descriptors()) { + bool insert_transition = + flag == INSERT_TRANSITION && !HasElementsTransition(); + + if (insert_transition && owns_descriptors()) { // In case the map owned its own descriptors, share the descriptors and // transfer ownership to the new map. Map* new_map; @@ -5124,8 +5076,8 @@ MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { if (added_elements->IsFailure()) return added_elements; new_map->set_elements_kind(kind); + new_map->InitializeDescriptors(instance_descriptors()); new_map->SetBackPointer(this); - new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors()); set_owns_descriptors(false); return new_map; } @@ -5136,24 +5088,12 @@ MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { Map* new_map; MaybeObject* maybe_new_map = Copy(); if (!maybe_new_map->To(&new_map)) return maybe_new_map; - ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors()); + new_map->set_elements_kind(kind); - if (flag == INSERT_TRANSITION && !HasElementsTransition()) { - // Map::Copy does not store the descriptor array in case it is empty, since - // it does not insert a back pointer; implicitly indicating that its - // descriptor array is empty. Since in this case we do want to insert a back - // pointer, we have to manually set the empty descriptor array to force a - // split. - if (!new_map->StoresOwnDescriptors()) { - ASSERT(new_map->NumberOfOwnDescriptors() == 0); - MaybeObject* maybe_failure = - new_map->SetDescriptors(GetHeap()->empty_descriptor_array()); - if (maybe_failure->IsFailure()) return maybe_failure; - } + if (insert_transition) { MaybeObject* added_elements = set_elements_transition_map(new_map); if (added_elements->IsFailure()) return added_elements; - new_map->SetBackPointer(this); } @@ -7467,14 +7407,8 @@ static void TrimDescriptorArray(Heap* heap, // Clear a possible back pointer in case the transition leads to a dead map. // Return true in case a back pointer has been cleared and false otherwise. -static bool ClearBackPointer(Heap* heap, - Map* target, - DescriptorArray* descriptors, - bool* descriptors_owner_died) { +static bool ClearBackPointer(Heap* heap, Map* target) { if (Marking::MarkBitFrom(target).Get()) return false; - if (target->instance_descriptors() == descriptors) { - *descriptors_owner_died = true; - } target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); return true; } @@ -7494,13 +7428,18 @@ void Map::ClearNonLiveTransitions(Heap* heap) { int transition_index = 0; - DescriptorArray* descriptors = t->descriptors(); + DescriptorArray* descriptors = instance_descriptors(); bool descriptors_owner_died = false; // Compact all live descriptors to the left. for (int i = 0; i < t->number_of_transitions(); ++i) { Map* target = t->GetTarget(i); - if (!ClearBackPointer(heap, target, descriptors, &descriptors_owner_died)) { + if (ClearBackPointer(heap, target)) { + if (target->instance_descriptors() == descriptors) { + descriptors_owner_died = true; + descriptors_owner_died = true; + } + } else { if (i != transition_index) { String* key = t->GetKey(i); t->SetKey(transition_index, key); @@ -7514,10 +7453,10 @@ void Map::ClearNonLiveTransitions(Heap* heap) { } if (t->HasElementsTransition() && - ClearBackPointer(heap, - t->elements_transition(), - descriptors, - &descriptors_owner_died)) { + ClearBackPointer(heap, t->elements_transition())) { + if (t->elements_transition()->instance_descriptors() == descriptors) { + descriptors_owner_died = true; + } t->ClearElementsTransition(); } else { // If there are no transitions to be cleared, return. @@ -7533,7 +7472,7 @@ void Map::ClearNonLiveTransitions(Heap* heap) { TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); } else { - t->set_descriptors(heap->empty_descriptor_array()); + ASSERT(descriptors == GetHeap()->empty_descriptor_array()); } } @@ -13015,8 +12954,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( descriptors->Sort(); - MaybeObject* maybe_failure = new_map->InitializeDescriptors(descriptors); - if (maybe_failure->IsFailure()) return maybe_failure; + new_map->InitializeDescriptors(descriptors); new_map->set_unused_property_fields(unused_property_fields); // Transform the object. diff --git a/src/objects.h b/src/objects.h index edc85dee0..91cafddcd 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2456,11 +2456,12 @@ class FixedDoubleArray: public FixedArrayBase { // DescriptorArrays are fixed arrays used to hold instance descriptors. // The format of the these objects is: -// [0]: Either Smi(0) if uninitialized, or a pointer to small fixed array: +// [0]: Number of descriptors +// [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array: // [0]: pointer to fixed array with enum cache // [1]: either Smi(0) or pointer to fixed array with indices -// [1]: first key -// [length() - kDescriptorSize]: last key +// [2]: first key +// [2 + number of descriptors * kDescriptorSize]: start of slack class DescriptorArray: public FixedArray { public: // WhitenessWitness is used to prove that a descriptor array is white @@ -4808,7 +4809,6 @@ 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(); @@ -4856,13 +4856,8 @@ class Map: public HeapObject { inline JSFunction* unchecked_constructor(); // [instance descriptors]: describes the object. - inline DescriptorArray* instance_descriptors(); - MUST_USE_RESULT inline MaybeObject* SetDescriptors( - DescriptorArray* descriptors); - static void SetDescriptors(Handle map, - Handle descriptors); - MUST_USE_RESULT inline MaybeObject* InitializeDescriptors( - DescriptorArray* descriptors); + DECL_ACCESSORS(instance_descriptors, DescriptorArray) + inline void InitializeDescriptors(DescriptorArray* descriptors); // [stub cache]: contains stubs compiled for this map. DECL_ACCESSORS(code_cache, Object) @@ -5124,11 +5119,12 @@ class Map: public HeapObject { // indirection. static const int kTransitionsOrBackPointerOffset = kConstructorOffset + kPointerSize; - static const int kCodeCacheOffset = + static const int kDescriptorsOffset = kTransitionsOrBackPointerOffset + kPointerSize; + static const int kCodeCacheOffset = + kDescriptorsOffset + kPointerSize; static const int kBitField3Offset = kCodeCacheOffset + kPointerSize; - static const int kPadStart = kBitField3Offset + kPointerSize; - static const int kSize = MAP_POINTER_ALIGN(kPadStart); + static const int kSize = kBitField3Offset + kPointerSize; // Layout of pointer fields. Heap iteration code relies on them // being continuously allocated. diff --git a/src/profile-generator.cc b/src/profile-generator.cc index d9259c8c2..b853f33cb 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -2009,11 +2009,6 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { Map::kConstructorOffset); if (map->HasTransitionArray()) { TransitionArray* transitions = map->transitions(); - DescriptorArray* descriptors = transitions->descriptors(); - TagObject(descriptors, "(map descriptors)"); - SetInternalReference(transitions, entry, - "descriptors", descriptors, - TransitionArray::kDescriptorsOffset); Object* back_pointer = transitions->back_pointer_storage(); TagObject(transitions->back_pointer_storage(), "(back pointer)"); @@ -2034,6 +2029,12 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { "backpointer", back_pointer, Map::kTransitionsOrBackPointerOffset); } + DescriptorArray* descriptors = map->instance_descriptors(); + TagObject(descriptors, "(map descriptors)"); + SetInternalReference(map, entry, + "descriptors", descriptors, + Map::kDescriptorsOffset); + SetInternalReference(map, entry, "code_cache", map->code_cache(), Map::kCodeCacheOffset); diff --git a/src/spaces.h b/src/spaces.h index 7ed0977e0..95c63d6b6 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -100,9 +100,6 @@ class Isolate; #define ASSERT_OBJECT_ALIGNED(address) \ ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0) -#define ASSERT_MAP_ALIGNED(address) \ - ASSERT((OffsetFrom(address) & kMapAlignmentMask) == 0) - #define ASSERT_OBJECT_SIZE(size) \ ASSERT((0 < size) && (size <= Page::kMaxNonCodeHeapObjectSize)) @@ -510,7 +507,7 @@ class MemoryChunk { static const size_t kHeaderSize = kWriteBarrierCounterOffset + kPointerSize; static const int kBodyOffset = - CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); + CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize); // The start offset of the object area in a page. Aligned to both maps and // code alignment to be suitable for both. Also aligned to 32 words because diff --git a/src/transitions-inl.h b/src/transitions-inl.h index 95a400e52..2df300283 100644 --- a/src/transitions-inl.h +++ b/src/transitions-inl.h @@ -84,23 +84,6 @@ void TransitionArray::set_elements_transition(Map* transition_map, } -Object** TransitionArray::GetDescriptorsSlot() { - return HeapObject::RawField(reinterpret_cast(this), - kDescriptorsOffset); -} - - -DescriptorArray* TransitionArray::descriptors() { - return DescriptorArray::cast(get(kDescriptorsIndex)); -} - - -void TransitionArray::set_descriptors(DescriptorArray* descriptors) { - ASSERT(descriptors->IsDescriptorArray()); - set(kDescriptorsIndex, descriptors); -} - - Object* TransitionArray::back_pointer_storage() { return get(kBackPointerStorageIndex); } diff --git a/src/transitions.cc b/src/transitions.cc index a65f3c3b2..56b6caf3d 100644 --- a/src/transitions.cc +++ b/src/transitions.cc @@ -73,7 +73,6 @@ static bool InsertionPointFound(String* key1, String* key2) { MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag, String* key, Map* target, - DescriptorArray* descriptors, Object* back_pointer) { TransitionArray* result; MaybeObject* maybe_result; @@ -88,16 +87,10 @@ MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag, result->NoIncrementalWriteBarrierSet(0, key, target); } result->set_back_pointer_storage(back_pointer); - result->set_descriptors(descriptors); return result; } -MaybeObject* TransitionArray::AllocateDescriptorsHolder() { - return AllocateRaw(kDescriptorsHolderSize); -} - - MaybeObject* TransitionArray::ExtendToFullTransitionArray() { ASSERT(!IsFullTransitionArray()); int nof = number_of_transitions(); @@ -109,7 +102,6 @@ MaybeObject* TransitionArray::ExtendToFullTransitionArray() { result->NoIncrementalWriteBarrierCopyFrom(this, kSimpleTransitionIndex, 0); } - result->set_descriptors(descriptors()); result->set_back_pointer_storage(back_pointer_storage()); return result; } @@ -128,8 +120,6 @@ MaybeObject* TransitionArray::CopyInsert(String* name, Map* target) { maybe_array = TransitionArray::Allocate(new_size); if (!maybe_array->To(&result)) return maybe_array; - result->set_descriptors(descriptors()); - if (HasElementsTransition()) { result->set_elements_transition(elements_transition()); } diff --git a/src/transitions.h b/src/transitions.h index 9643a6181..0a660261c 100644 --- a/src/transitions.h +++ b/src/transitions.h @@ -39,13 +39,22 @@ namespace internal { // TransitionArrays are fixed arrays used to hold map transitions for property, -// constant, and element changes. -// The format of the these objects is: -// [0] Descriptor array -// [1] Undefined or back pointer map -// [2] Smi(0) or elements transition map -// [3] Smi(0) or fixed array of prototype transitions -// [4] First transition +// constant, and element changes. They can either be simple transition arrays +// that store a single property transition, or a full transition array that has +// space for elements transitions, prototype transitions and multiple property +// transitons. The details related to property transitions are accessed in the +// descriptor array of the target map. In the case of a simple transition, the +// key is also read from the descriptor array of the target map. +// +// The simple format of the these objects is: +// [0] Undefined or back pointer map +// [1] Single transition +// +// The full format is: +// [0] Undefined or back pointer map +// [1] Smi(0) or elements transition map +// [2] Smi(0) or fixed array of prototype transitions +// [3] First transition // [length() - kTransitionSize] Last transition class TransitionArray: public FixedArray { public: @@ -71,10 +80,6 @@ class TransitionArray: public FixedArray { inline bool HasElementsTransition(); inline void ClearElementsTransition(); - inline Object** GetDescriptorsSlot(); - inline DescriptorArray* descriptors(); - inline void set_descriptors(DescriptorArray* descriptors); - inline Object* back_pointer_storage(); inline void set_back_pointer_storage( Object* back_pointer, @@ -102,11 +107,8 @@ class TransitionArray: public FixedArray { SimpleTransitionFlag flag, String* key, Map* target, - DescriptorArray* descriptors, Object* back_pointer); - static MUST_USE_RESULT MaybeObject* AllocateDescriptorsHolder(); - MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray(); // Copy the transition array, inserting a new transition. @@ -125,7 +127,6 @@ class TransitionArray: public FixedArray { // Allocates a TransitionArray. MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions); - bool IsDescriptorsHolder() { return length() == kDescriptorsHolderSize; } bool IsSimpleTransition() { return length() == kSimpleTransitionSize; } bool IsFullTransitionArray() { return length() >= kFirstIndex; } @@ -135,24 +136,20 @@ class TransitionArray: public FixedArray { // Constant for denoting key was not found. static const int kNotFound = -1; - static const int kDescriptorsIndex = 0; - static const int kBackPointerStorageIndex = 1; - static const int kDescriptorsHolderSize = 2; + static const int kBackPointerStorageIndex = 0; // Layout for full transition arrays. - static const int kElementsTransitionIndex = 2; - static const int kPrototypeTransitionsIndex = 3; - static const int kFirstIndex = 4; + static const int kElementsTransitionIndex = 1; + static const int kPrototypeTransitionsIndex = 2; + static const int kFirstIndex = 3; // Layout for simple transition arrays. - static const int kSimpleTransitionTarget = 2; - static const int kSimpleTransitionSize = 3; + static const int kSimpleTransitionTarget = 1; + static const int kSimpleTransitionSize = 2; static const int kSimpleTransitionIndex = 0; STATIC_ASSERT(kSimpleTransitionIndex != kNotFound); - static const int kDescriptorsOffset = FixedArray::kHeaderSize; - static const int kBackPointerStorageOffset = kDescriptorsOffset + - kPointerSize; + static const int kBackPointerStorageOffset = FixedArray::kHeaderSize; // Layout for the full transition array header. static const int kElementsTransitionOffset = kBackPointerStorageOffset + diff --git a/src/v8globals.h b/src/v8globals.h index 37c4c65a8..648413fed 100644 --- a/src/v8globals.h +++ b/src/v8globals.h @@ -52,15 +52,6 @@ const intptr_t kPointerAlignmentMask = kPointerAlignment - 1; const intptr_t kDoubleAlignment = 8; const intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1; -// Desired alignment for maps. -#if V8_HOST_ARCH_64_BIT -const intptr_t kMapAlignmentBits = kObjectAlignmentBits; -#else -const intptr_t kMapAlignmentBits = kObjectAlignmentBits + 3; -#endif -const intptr_t kMapAlignment = (1 << kMapAlignmentBits); -const intptr_t kMapAlignmentMask = kMapAlignment - 1; - // Desired alignment for generated code is 32 bytes (to improve cache line // utilization). const int kCodeAlignmentBits = 5; @@ -396,10 +387,6 @@ enum StateTag { #define POINTER_SIZE_ALIGN(value) \ (((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask) -// MAP_POINTER_ALIGN returns the value aligned as a map pointer. -#define MAP_POINTER_ALIGN(value) \ - (((value) + kMapAlignmentMask) & ~kMapAlignmentMask) - // CODE_POINTER_ALIGN returns the value aligned as a generated code segment. #define CODE_POINTER_ALIGN(value) \ (((value) + kCodeAlignmentMask) & ~kCodeAlignmentMask) diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 49849d8c4..ee0635f91 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -2905,28 +2905,7 @@ void MacroAssembler::LoadUint32(XMMRegister dst, void MacroAssembler::LoadInstanceDescriptors(Register map, Register descriptors) { - Register temp = descriptors; - movq(temp, FieldOperand(map, Map::kTransitionsOrBackPointerOffset)); - - Label ok, fail, load_from_back_pointer; - CheckMap(temp, - isolate()->factory()->fixed_array_map(), - &fail, - DONT_DO_SMI_CHECK); - movq(descriptors, FieldOperand(temp, TransitionArray::kDescriptorsOffset)); - jmp(&ok); - - bind(&fail); - CompareRoot(temp, Heap::kUndefinedValueRootIndex); - j(not_equal, &load_from_back_pointer, Label::kNear); - Move(descriptors, isolate()->factory()->empty_descriptor_array()); - jmp(&ok); - - bind(&load_from_back_pointer); - movq(temp, FieldOperand(temp, Map::kTransitionsOrBackPointerOffset)); - movq(descriptors, FieldOperand(temp, TransitionArray::kDescriptorsOffset)); - - bind(&ok); + movq(descriptors, FieldOperand(map, Map::kDescriptorsOffset)); } diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index 24c7f1fdc..7ba2583da 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -158,7 +158,7 @@ TEST(StressJS) { Handle new_descriptors = FACTORY->NewDescriptorArray(0, 1); v8::internal::DescriptorArray::WhitenessWitness witness(*new_descriptors); - v8::internal::Map::SetDescriptors(map, new_descriptors); + map->set_instance_descriptors(*new_descriptors); CallbacksDescriptor d(*name, *foreign, diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 4f7421be8..52359711d 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -1676,18 +1676,8 @@ TEST(MapHasDescriptorsAndTransitions) { CHECK_NE(NULL, map); const v8::HeapGraphNode* own_descriptors = GetProperty( map, v8::HeapGraphEdge::kInternal, "descriptors"); - CHECK_EQ(NULL, own_descriptors); + CHECK_NE(NULL, own_descriptors); const v8::HeapGraphNode* own_transitions = GetProperty( map, v8::HeapGraphEdge::kInternal, "transitions"); CHECK_EQ(NULL, own_transitions); - - const v8::HeapGraphNode* back_pointer_map = - GetProperty(map, v8::HeapGraphEdge::kInternal, "backpointer"); - CHECK_NE(NULL, back_pointer_map); - const v8::HeapGraphNode* descriptors = GetProperty( - back_pointer_map, v8::HeapGraphEdge::kInternal, "descriptors"); - CHECK_NE(NULL, descriptors); - const v8::HeapGraphNode* transitions = GetProperty( - back_pointer_map, v8::HeapGraphEdge::kInternal, "transitions"); - CHECK_NE(NULL, transitions); } -- 2.34.1