From: rmcilroy@chromium.org Date: Tue, 3 Jun 2014 16:22:10 +0000 (+0000) Subject: Add support for extended constant pool arrays. X-Git-Tag: upstream/4.7.83~8829 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=97c962c25591b96943ccccd4b10dae487223c0d1;p=platform%2Fupstream%2Fv8.git Add support for extended constant pool arrays. This CL adds support for ConstantPoolArrays which contain an extended section. This will be used to enable larger constant pools than can be addressed by a single ldr with immediate offset instruction (which has a limit of a 4KB range). Extended constant pools will have a small section, which is addressable via a single ldr instruction, and an extended section, which will require a multi- instruction sequence to load from. Currently, no code uses the extended ConstantPoolArray's - this change will be made in a followup CL. A number of changes are made to the ConstantPoolArray object in order to support this: - Small section layout is now entirely defined by the small layout bitmaps. - The ConstantPoolArray no longer extends FixedArrayBase since the length field is not useful for extended layouts. - Enums are used to represent the type of an entry and the layout section. - An iterator can be used to iterate through all elements of a given type. - A number of tests were added for these features. R=ulan@chromium.org Review URL: https://codereview.chromium.org/304143002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21653 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index a71bfca..ee4def9 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -3554,11 +3554,15 @@ void ConstantPoolBuilder::AddEntry(Assembler* assm, // Check if we still have room for another entry given Arm's ldr and vldr // immediate offset range. - if (!(is_uint12(ConstantPoolArray::SizeFor(count_of_64bit_, - count_of_code_ptr_, - count_of_heap_ptr_, - count_of_32bit_))) && - is_uint10(ConstantPoolArray::SizeFor(count_of_64bit_, 0, 0, 0))) { + // TODO(rmcilroy): Avoid creating a new object here when we support + // extended constant pools. + ConstantPoolArray::NumberOfEntries total(count_of_64bit_, + count_of_code_ptr_, + count_of_heap_ptr_, + count_of_32bit_); + ConstantPoolArray::NumberOfEntries int64_counts(count_of_64bit_, 0, 0, 0); + if (!(is_uint12(ConstantPoolArray::SizeFor(total)) && + is_uint10(ConstantPoolArray::SizeFor(int64_counts)))) { assm->set_constant_pool_full(); } } @@ -3577,20 +3581,26 @@ Handle ConstantPoolBuilder::New(Isolate* isolate) { if (IsEmpty()) { return isolate->factory()->empty_constant_pool_array(); } else { - return isolate->factory()->NewConstantPoolArray(count_of_64bit_, - count_of_code_ptr_, - count_of_heap_ptr_, - count_of_32bit_); + ConstantPoolArray::NumberOfEntries small(count_of_64bit_, + count_of_code_ptr_, + count_of_heap_ptr_, + count_of_32bit_); + return isolate->factory()->NewConstantPoolArray(small); } } void ConstantPoolBuilder::Populate(Assembler* assm, ConstantPoolArray* constant_pool) { - ASSERT(constant_pool->count_of_int64_entries() == count_of_64bit_); - ASSERT(constant_pool->count_of_code_ptr_entries() == count_of_code_ptr_); - ASSERT(constant_pool->count_of_heap_ptr_entries() == count_of_heap_ptr_); - ASSERT(constant_pool->count_of_int32_entries() == count_of_32bit_); + ConstantPoolArray::LayoutSection section = ConstantPoolArray::SMALL_SECTION; + ASSERT(count_of_64bit_ == + constant_pool->number_of_entries(ConstantPoolArray::INT64, section)); + ASSERT(count_of_code_ptr_ == + constant_pool->number_of_entries(ConstantPoolArray::CODE_PTR, section)); + ASSERT(count_of_heap_ptr_ == + constant_pool->number_of_entries(ConstantPoolArray::HEAP_PTR, section)); + ASSERT(count_of_32bit_ == + constant_pool->number_of_entries(ConstantPoolArray::INT32, section)); ASSERT(entries_.size() == merged_indexes_.size()); int index_64bit = 0; @@ -3616,7 +3626,7 @@ void ConstantPoolBuilder::Populate(Assembler* assm, offset = constant_pool->OffsetOfElementAt(index_code_ptr) - kHeapObjectTag; constant_pool->set(index_code_ptr++, - reinterpret_cast(rinfo->data())); + reinterpret_cast
(rinfo->data())); } else { ASSERT(IsHeapPtrEntry(rmode)); offset = constant_pool->OffsetOfElementAt(index_heap_ptr) - diff --git a/src/factory.cc b/src/factory.cc index 537ca17..33d856f 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -115,18 +115,23 @@ Handle Factory::NewFixedDoubleArrayWithHoles( Handle Factory::NewConstantPoolArray( - int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries) { - ASSERT(number_of_int64_entries > 0 || number_of_code_ptr_entries > 0 || - number_of_heap_ptr_entries > 0 || number_of_int32_entries > 0); + const ConstantPoolArray::NumberOfEntries& small) { + ASSERT(small.total_count() > 0); CALL_HEAP_FUNCTION( isolate(), - isolate()->heap()->AllocateConstantPoolArray(number_of_int64_entries, - number_of_code_ptr_entries, - number_of_heap_ptr_entries, - number_of_int32_entries), + isolate()->heap()->AllocateConstantPoolArray(small), + ConstantPoolArray); +} + + +Handle Factory::NewExtendedConstantPoolArray( + const ConstantPoolArray::NumberOfEntries& small, + const ConstantPoolArray::NumberOfEntries& extended) { + ASSERT(small.total_count() > 0); + ASSERT(extended.total_count() > 0); + CALL_HEAP_FUNCTION( + isolate(), + isolate()->heap()->AllocateExtendedConstantPoolArray(small, extended), ConstantPoolArray); } diff --git a/src/factory.h b/src/factory.h index 0513ac5..7ef8911 100644 --- a/src/factory.h +++ b/src/factory.h @@ -45,10 +45,11 @@ class Factory V8_FINAL { PretenureFlag pretenure = NOT_TENURED); Handle NewConstantPoolArray( - int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries); + const ConstantPoolArray::NumberOfEntries& small); + + Handle NewExtendedConstantPoolArray( + const ConstantPoolArray::NumberOfEntries& small, + const ConstantPoolArray::NumberOfEntries& extended); Handle NewOrderedHashSet(); Handle NewOrderedHashMap(); diff --git a/src/heap.cc b/src/heap.cc index fce6bf8..7c1d61a 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -1808,7 +1808,9 @@ Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, STATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) == 0); // NOLINT -STATIC_ASSERT((ConstantPoolArray::kHeaderSize & +STATIC_ASSERT((ConstantPoolArray::kFirstEntryOffset & + kDoubleAlignmentMask) == 0); // NOLINT +STATIC_ASSERT((ConstantPoolArray::kExtendedFirstOffset & kDoubleAlignmentMask) == 0); // NOLINT @@ -4046,23 +4048,26 @@ AllocationResult Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src, AllocationResult Heap::CopyConstantPoolArrayWithMap(ConstantPoolArray* src, Map* map) { - int int64_entries = src->count_of_int64_entries(); - int code_ptr_entries = src->count_of_code_ptr_entries(); - int heap_ptr_entries = src->count_of_heap_ptr_entries(); - int int32_entries = src->count_of_int32_entries(); HeapObject* obj; - { AllocationResult allocation = - AllocateConstantPoolArray(int64_entries, code_ptr_entries, - heap_ptr_entries, int32_entries); + if (src->is_extended_layout()) { + ConstantPoolArray::NumberOfEntries small(src, + ConstantPoolArray::SMALL_SECTION); + ConstantPoolArray::NumberOfEntries extended(src, + ConstantPoolArray::EXTENDED_SECTION); + AllocationResult allocation = + AllocateExtendedConstantPoolArray(small, extended); + if (!allocation.To(&obj)) return allocation; + } else { + ConstantPoolArray::NumberOfEntries small(src, + ConstantPoolArray::SMALL_SECTION); + AllocationResult allocation = AllocateConstantPoolArray(small); if (!allocation.To(&obj)) return allocation; } obj->set_map_no_write_barrier(map); - int size = ConstantPoolArray::SizeFor( - int64_entries, code_ptr_entries, heap_ptr_entries, int32_entries); CopyBlock( - obj->address() + ConstantPoolArray::kLengthOffset, - src->address() + ConstantPoolArray::kLengthOffset, - size - ConstantPoolArray::kLengthOffset); + obj->address() + ConstantPoolArray::kFirstEntryOffset, + src->address() + ConstantPoolArray::kFirstEntryOffset, + src->size() - ConstantPoolArray::kFirstEntryOffset); return obj; } @@ -4154,22 +4159,10 @@ AllocationResult Heap::AllocateRawFixedDoubleArray(int length, } -AllocationResult Heap::AllocateConstantPoolArray(int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries) { - CHECK(number_of_int64_entries >= 0 && - number_of_int64_entries <= ConstantPoolArray::kMaxEntriesPerType && - number_of_code_ptr_entries >= 0 && - number_of_code_ptr_entries <= ConstantPoolArray::kMaxEntriesPerType && - number_of_heap_ptr_entries >= 0 && - number_of_heap_ptr_entries <= ConstantPoolArray::kMaxEntriesPerType && - number_of_int32_entries >= 0 && - number_of_int32_entries <= ConstantPoolArray::kMaxEntriesPerType); - int size = ConstantPoolArray::SizeFor(number_of_int64_entries, - number_of_code_ptr_entries, - number_of_heap_ptr_entries, - number_of_int32_entries); +AllocationResult Heap::AllocateConstantPoolArray( + const ConstantPoolArray::NumberOfEntries& small) { + CHECK(small.are_in_range(0, ConstantPoolArray::kMaxSmallEntriesPerType)); + int size = ConstantPoolArray::SizeFor(small); #ifndef V8_HOST_ARCH_64_BIT size += kPointerSize; #endif @@ -4183,39 +4176,47 @@ AllocationResult Heap::AllocateConstantPoolArray(int number_of_int64_entries, object->set_map_no_write_barrier(constant_pool_array_map()); ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object); - constant_pool->Init(number_of_int64_entries, - number_of_code_ptr_entries, - number_of_heap_ptr_entries, - number_of_int32_entries); - if (number_of_code_ptr_entries > 0) { - int offset = - constant_pool->OffsetOfElementAt(constant_pool->first_code_ptr_index()); - MemsetPointer( - reinterpret_cast(HeapObject::RawField(constant_pool, offset)), - isolate()->builtins()->builtin(Builtins::kIllegal)->entry(), - number_of_code_ptr_entries); - } - if (number_of_heap_ptr_entries > 0) { - int offset = - constant_pool->OffsetOfElementAt(constant_pool->first_heap_ptr_index()); - MemsetPointer( - HeapObject::RawField(constant_pool, offset), - undefined_value(), - number_of_heap_ptr_entries); + constant_pool->Init(small); + constant_pool->ClearPtrEntries(isolate()); + return constant_pool; +} + + +AllocationResult Heap::AllocateExtendedConstantPoolArray( + const ConstantPoolArray::NumberOfEntries& small, + const ConstantPoolArray::NumberOfEntries& extended) { + CHECK(small.are_in_range(0, ConstantPoolArray::kMaxSmallEntriesPerType)); + CHECK(extended.are_in_range(0, kMaxInt)); + int size = ConstantPoolArray::SizeForExtended(small, extended); +#ifndef V8_HOST_ARCH_64_BIT + size += kPointerSize; +#endif + AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, TENURED); + + HeapObject* object; + { AllocationResult allocation = AllocateRaw(size, space, OLD_POINTER_SPACE); + if (!allocation.To(&object)) return allocation; } + object = EnsureDoubleAligned(this, object, size); + object->set_map_no_write_barrier(constant_pool_array_map()); + + ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object); + constant_pool->InitExtended(small, extended); + constant_pool->ClearPtrEntries(isolate()); return constant_pool; } AllocationResult Heap::AllocateEmptyConstantPoolArray() { - int size = ConstantPoolArray::SizeFor(0, 0, 0, 0); + ConstantPoolArray::NumberOfEntries small(0, 0, 0, 0); + int size = ConstantPoolArray::SizeFor(small); HeapObject* result; { AllocationResult allocation = AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE); if (!allocation.To(&result)) return allocation; } result->set_map_no_write_barrier(constant_pool_array_map()); - ConstantPoolArray::cast(result)->Init(0, 0, 0, 0); + ConstantPoolArray::cast(result)->Init(small); return result; } diff --git a/src/heap.h b/src/heap.h index 3945515..549c03f 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1873,10 +1873,11 @@ class Heap { ConstantPoolArray* src, Map* map); MUST_USE_RESULT AllocationResult AllocateConstantPoolArray( - int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries); + const ConstantPoolArray::NumberOfEntries& small); + + MUST_USE_RESULT AllocationResult AllocateExtendedConstantPoolArray( + const ConstantPoolArray::NumberOfEntries& small, + const ConstantPoolArray::NumberOfEntries& extended); // Allocates an external array of the specified length and type. MUST_USE_RESULT AllocationResult AllocateExternalArray( diff --git a/src/mark-compact.cc b/src/mark-compact.cc index 32aba56..1e1a737 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -2847,10 +2847,11 @@ void MarkCompactCollector::MigrateObject(HeapObject* dst, SlotsBuffer::IGNORE_OVERFLOW); } } else if (compacting_ && dst->IsConstantPoolArray()) { - ConstantPoolArray* constant_pool = ConstantPoolArray::cast(dst); - for (int i = 0; i < constant_pool->count_of_code_ptr_entries(); i++) { + ConstantPoolArray* array = ConstantPoolArray::cast(dst); + ConstantPoolArray::Iterator code_iter(array, ConstantPoolArray::CODE_PTR); + while (!code_iter.is_finished()) { Address code_entry_slot = - dst_addr + constant_pool->OffsetOfElementAt(i); + dst_addr + array->OffsetOfElementAt(code_iter.next_index()); Address code_entry = Memory::Address_at(code_entry_slot); if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) { diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 5ce04b9..762354e 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -378,12 +378,14 @@ void FixedDoubleArray::FixedDoubleArrayVerify() { void ConstantPoolArray::ConstantPoolArrayVerify() { CHECK(IsConstantPoolArray()); - for (int i = 0; i < count_of_code_ptr_entries(); i++) { - Address code_entry = get_code_ptr_entry(first_code_ptr_index() + i); + ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR); + while (!code_iter.is_finished()) { + Address code_entry = get_code_ptr_entry(code_iter.next_index()); VerifyPointer(Code::GetCodeFromTargetAddress(code_entry)); } - for (int i = 0; i < count_of_heap_ptr_entries(); i++) { - VerifyObjectField(OffsetOfElementAt(first_heap_ptr_index() + i)); + ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR); + while (!heap_iter.is_finished()) { + VerifyObjectField(OffsetOfElementAt(heap_iter.next_index())); } } diff --git a/src/objects-inl.h b/src/objects-inl.h index 872fa1c..36d1aa1 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -2217,152 +2217,281 @@ void FixedDoubleArray::FillWithHoles(int from, int to) { } -void ConstantPoolArray::set_weak_object_state( - ConstantPoolArray::WeakObjectState state) { - int old_layout_field = READ_INT_FIELD(this, kArrayLayoutOffset); - int new_layout_field = WeakObjectStateField::update(old_layout_field, state); - WRITE_INT_FIELD(this, kArrayLayoutOffset, new_layout_field); +bool ConstantPoolArray::is_extended_layout() { + uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset); + return IsExtendedField::decode(small_layout_1); } -ConstantPoolArray::WeakObjectState ConstantPoolArray::get_weak_object_state() { - int layout_field = READ_INT_FIELD(this, kArrayLayoutOffset); - return WeakObjectStateField::decode(layout_field); +ConstantPoolArray::LayoutSection ConstantPoolArray::final_section() { + return is_extended_layout() ? EXTENDED_SECTION : SMALL_SECTION; } -int ConstantPoolArray::first_int64_index() { - return 0; +int ConstantPoolArray::first_extended_section_index() { + ASSERT(is_extended_layout()); + uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset); + return TotalCountField::decode(small_layout_2); } -int ConstantPoolArray::first_code_ptr_index() { - int layout_field = READ_INT_FIELD(this, kArrayLayoutOffset); - return first_int64_index() + - NumberOfInt64EntriesField::decode(layout_field); +int ConstantPoolArray::get_extended_section_header_offset() { + return RoundUp(SizeFor(NumberOfEntries(this, SMALL_SECTION)), kInt64Size); } -int ConstantPoolArray::first_heap_ptr_index() { - int layout_field = READ_INT_FIELD(this, kArrayLayoutOffset); - return first_code_ptr_index() + - NumberOfCodePtrEntriesField::decode(layout_field); +ConstantPoolArray::WeakObjectState ConstantPoolArray::get_weak_object_state() { + uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset); + return WeakObjectStateField::decode(small_layout_2); } -int ConstantPoolArray::first_int32_index() { - int layout_field = READ_INT_FIELD(this, kArrayLayoutOffset); - return first_heap_ptr_index() + - NumberOfHeapPtrEntriesField::decode(layout_field); +void ConstantPoolArray::set_weak_object_state( + ConstantPoolArray::WeakObjectState state) { + uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset); + small_layout_2 = WeakObjectStateField::update(small_layout_2, state); + WRITE_INT32_FIELD(this, kSmallLayout2Offset, small_layout_2); } -int ConstantPoolArray::count_of_int64_entries() { - return first_code_ptr_index(); -} +int ConstantPoolArray::first_index(Type type, LayoutSection section) { + int index = 0; + if (section == EXTENDED_SECTION) { + ASSERT(is_extended_layout()); + index += first_extended_section_index(); + } + for (Type type_iter = FIRST_TYPE; type_iter < type; + type_iter = next_type(type_iter)) { + index += number_of_entries(type_iter, section); + } -int ConstantPoolArray::count_of_code_ptr_entries() { - return first_heap_ptr_index() - first_code_ptr_index(); + return index; } -int ConstantPoolArray::count_of_heap_ptr_entries() { - return first_int32_index() - first_heap_ptr_index(); +int ConstantPoolArray::last_index(Type type, LayoutSection section) { + return first_index(type, section) + number_of_entries(type, section) - 1; } -int ConstantPoolArray::count_of_int32_entries() { - return length() - first_int32_index(); +int ConstantPoolArray::number_of_entries(Type type, LayoutSection section) { + if (section == SMALL_SECTION) { + uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset); + uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset); + switch (type) { + case INT64: + return Int64CountField::decode(small_layout_1); + case CODE_PTR: + return CodePtrCountField::decode(small_layout_1); + case HEAP_PTR: + return HeapPtrCountField::decode(small_layout_1); + case INT32: + return Int32CountField::decode(small_layout_2); + default: + UNREACHABLE(); + return 0; + } + } else { + ASSERT(section == EXTENDED_SECTION && is_extended_layout()); + int offset = get_extended_section_header_offset(); + switch (type) { + case INT64: + offset += kExtendedInt64CountOffset; + break; + case CODE_PTR: + offset += kExtendedCodePtrCountOffset; + break; + case HEAP_PTR: + offset += kExtendedHeapPtrCountOffset; + break; + case INT32: + offset += kExtendedInt32CountOffset; + break; + default: + UNREACHABLE(); + } + return READ_INT_FIELD(this, offset); + } } -void ConstantPoolArray::Init(int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries) { - set_length(number_of_int64_entries + - number_of_code_ptr_entries + - number_of_heap_ptr_entries + - number_of_int32_entries); - int layout_field = - NumberOfInt64EntriesField::encode(number_of_int64_entries) | - NumberOfCodePtrEntriesField::encode(number_of_code_ptr_entries) | - NumberOfHeapPtrEntriesField::encode(number_of_heap_ptr_entries) | - WeakObjectStateField::encode(NO_WEAK_OBJECTS); - WRITE_INT_FIELD(this, kArrayLayoutOffset, layout_field); +ConstantPoolArray::Type ConstantPoolArray::get_type(int index) { + LayoutSection section; + if (is_extended_layout() && index >= first_extended_section_index()) { + section = EXTENDED_SECTION; + } else { + section = SMALL_SECTION; + } + + Type type = FIRST_TYPE; + while (index > last_index(type, section)) { + type = next_type(type); + } + ASSERT(type <= LAST_TYPE); + return type; } int64_t ConstantPoolArray::get_int64_entry(int index) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= 0 && index < first_code_ptr_index()); + ASSERT(get_type(index) == INT64); return READ_INT64_FIELD(this, OffsetOfElementAt(index)); } + double ConstantPoolArray::get_int64_entry_as_double(int index) { STATIC_ASSERT(kDoubleSize == kInt64Size); ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= 0 && index < first_code_ptr_index()); + ASSERT(get_type(index) == INT64); return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index)); } Address ConstantPoolArray::get_code_ptr_entry(int index) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_code_ptr_index() && index < first_heap_ptr_index()); + ASSERT(get_type(index) == CODE_PTR); return reinterpret_cast
(READ_FIELD(this, OffsetOfElementAt(index))); } Object* ConstantPoolArray::get_heap_ptr_entry(int index) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_heap_ptr_index() && index < first_int32_index()); + ASSERT(get_type(index) == HEAP_PTR); return READ_FIELD(this, OffsetOfElementAt(index)); } int32_t ConstantPoolArray::get_int32_entry(int index) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_int32_index() && index < length()); + ASSERT(get_type(index) == INT32); return READ_INT32_FIELD(this, OffsetOfElementAt(index)); } +void ConstantPoolArray::set(int index, int64_t value) { + ASSERT(map() == GetHeap()->constant_pool_array_map()); + ASSERT(get_type(index) == INT64); + WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value); +} + + +void ConstantPoolArray::set(int index, double value) { + STATIC_ASSERT(kDoubleSize == kInt64Size); + ASSERT(map() == GetHeap()->constant_pool_array_map()); + ASSERT(get_type(index) == INT64); + WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value); +} + + void ConstantPoolArray::set(int index, Address value) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_code_ptr_index() && index < first_heap_ptr_index()); + ASSERT(get_type(index) == CODE_PTR); WRITE_FIELD(this, OffsetOfElementAt(index), reinterpret_cast(value)); } void ConstantPoolArray::set(int index, Object* value) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_code_ptr_index() && index < first_int32_index()); + ASSERT(get_type(index) == HEAP_PTR); WRITE_FIELD(this, OffsetOfElementAt(index), value); WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value); } -void ConstantPoolArray::set(int index, int64_t value) { +void ConstantPoolArray::set(int index, int32_t value) { ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_int64_index() && index < first_code_ptr_index()); - WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value); + ASSERT(get_type(index) == INT32); + WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value); } -void ConstantPoolArray::set(int index, double value) { - STATIC_ASSERT(kDoubleSize == kInt64Size); - ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= first_int64_index() && index < first_code_ptr_index()); - WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value); +void ConstantPoolArray::Init(const NumberOfEntries& small) { + uint32_t small_layout_1 = + Int64CountField::encode(small.count_of(INT64)) | + CodePtrCountField::encode(small.count_of(CODE_PTR)) | + HeapPtrCountField::encode(small.count_of(HEAP_PTR)) | + IsExtendedField::encode(false); + uint32_t small_layout_2 = + Int32CountField::encode(small.count_of(INT32)) | + TotalCountField::encode(small.total_count()) | + WeakObjectStateField::encode(NO_WEAK_OBJECTS); + WRITE_UINT32_FIELD(this, kSmallLayout1Offset, small_layout_1); + WRITE_UINT32_FIELD(this, kSmallLayout2Offset, small_layout_2); + if (kHeaderSize != kFirstEntryOffset) { + ASSERT(kFirstEntryOffset - kHeaderSize == kInt32Size); + WRITE_UINT32_FIELD(this, kHeaderSize, 0); // Zero out header padding. + } } -void ConstantPoolArray::set(int index, int32_t value) { - ASSERT(map() == GetHeap()->constant_pool_array_map()); - ASSERT(index >= this->first_int32_index() && index < length()); - WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value); +void ConstantPoolArray::InitExtended(const NumberOfEntries& small, + const NumberOfEntries& extended) { + // Initialize small layout fields first. + Init(small); + + // Set is_extended_layout field. + uint32_t small_layout_1 = READ_UINT32_FIELD(this, kSmallLayout1Offset); + small_layout_1 = IsExtendedField::update(small_layout_1, true); + WRITE_INT32_FIELD(this, kSmallLayout1Offset, small_layout_1); + + // Initialize the extended layout fields. + int extended_header_offset = get_extended_section_header_offset(); + WRITE_INT_FIELD(this, extended_header_offset + kExtendedInt64CountOffset, + extended.count_of(INT64)); + WRITE_INT_FIELD(this, extended_header_offset + kExtendedCodePtrCountOffset, + extended.count_of(CODE_PTR)); + WRITE_INT_FIELD(this, extended_header_offset + kExtendedHeapPtrCountOffset, + extended.count_of(HEAP_PTR)); + WRITE_INT_FIELD(this, extended_header_offset + kExtendedInt32CountOffset, + extended.count_of(INT32)); +} + + +int ConstantPoolArray::size() { + NumberOfEntries small(this, SMALL_SECTION); + if (!is_extended_layout()) { + return SizeFor(small); + } else { + NumberOfEntries extended(this, EXTENDED_SECTION); + return SizeForExtended(small, extended); + } +} + + +int ConstantPoolArray::length() { + uint32_t small_layout_2 = READ_UINT32_FIELD(this, kSmallLayout2Offset); + int length = TotalCountField::decode(small_layout_2); + if (is_extended_layout()) { + length += number_of_entries(INT64, EXTENDED_SECTION) + + number_of_entries(CODE_PTR, EXTENDED_SECTION) + + number_of_entries(HEAP_PTR, EXTENDED_SECTION) + + number_of_entries(INT32, EXTENDED_SECTION); + } + return length; +} + + +int ConstantPoolArray::Iterator::next_index() { + ASSERT(!is_finished()); + int ret = next_index_++; + update_section(); + return ret; +} + + +bool ConstantPoolArray::Iterator::is_finished() { + return next_index_ > array_->last_index(type_, final_section_); +} + + +void ConstantPoolArray::Iterator::update_section() { + if (next_index_ > array_->last_index(type_, current_section_) && + current_section_ != final_section_) { + ASSERT(final_section_ == EXTENDED_SECTION); + current_section_ = EXTENDED_SECTION; + next_index_ = array_->first_index(type_, EXTENDED_SECTION); + } } @@ -3977,11 +4106,7 @@ int HeapObject::SizeFromMap(Map* map) { reinterpret_cast(this)->length()); } if (instance_type == CONSTANT_POOL_ARRAY_TYPE) { - return ConstantPoolArray::SizeFor( - reinterpret_cast(this)->count_of_int64_entries(), - reinterpret_cast(this)->count_of_code_ptr_entries(), - reinterpret_cast(this)->count_of_heap_ptr_entries(), - reinterpret_cast(this)->count_of_int32_entries()); + return reinterpret_cast(this)->size(); } if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) { diff --git a/src/objects-printer.cc b/src/objects-printer.cc index 6595acc..c51c04e 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -579,19 +579,36 @@ void FixedDoubleArray::FixedDoubleArrayPrint(FILE* out) { void ConstantPoolArray::ConstantPoolArrayPrint(FILE* out) { HeapObject::PrintHeader(out, "ConstantPoolArray"); PrintF(out, " - length: %d", length()); - for (int i = 0; i < length(); i++) { - if (i < first_code_ptr_index()) { + for (int i = 0; i <= last_index(INT32, SMALL_SECTION); i++) { + if (i < last_index(INT64, SMALL_SECTION)) { PrintF(out, "\n [%d]: double: %g", i, get_int64_entry_as_double(i)); - } else if (i < first_heap_ptr_index()) { + } else if (i <= last_index(CODE_PTR, SMALL_SECTION)) { PrintF(out, "\n [%d]: code target pointer: %p", i, reinterpret_cast(get_code_ptr_entry(i))); - } else if (i < first_int32_index()) { + } else if (i <= last_index(HEAP_PTR, SMALL_SECTION)) { PrintF(out, "\n [%d]: heap pointer: %p", i, reinterpret_cast(get_heap_ptr_entry(i))); - } else { + } else if (i <= last_index(INT32, SMALL_SECTION)) { PrintF(out, "\n [%d]: int32: %d", i, get_int32_entry(i)); } } + if (is_extended_layout()) { + PrintF(out, "\n Extended section:"); + for (int i = first_extended_section_index(); + i <= last_index(INT32, EXTENDED_SECTION); i++) { + if (i < last_index(INT64, EXTENDED_SECTION)) { + PrintF(out, "\n [%d]: double: %g", i, get_int64_entry_as_double(i)); + } else if (i <= last_index(CODE_PTR, EXTENDED_SECTION)) { + PrintF(out, "\n [%d]: code target pointer: %p", i, + reinterpret_cast(get_code_ptr_entry(i))); + } else if (i <= last_index(HEAP_PTR, EXTENDED_SECTION)) { + PrintF(out, "\n [%d]: heap pointer: %p", i, + reinterpret_cast(get_heap_ptr_entry(i))); + } else if (i <= last_index(INT32, EXTENDED_SECTION)) { + PrintF(out, "\n [%d]: int32: %d", i, get_int32_entry(i)); + } + } + } PrintF(out, "\n"); } diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h index 057b8ae..d5681b8 100644 --- a/src/objects-visiting-inl.h +++ b/src/objects-visiting-inl.h @@ -498,23 +498,24 @@ template void StaticMarkingVisitor::VisitConstantPoolArray( Map* map, HeapObject* object) { Heap* heap = map->GetHeap(); - ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object); - for (int i = 0; i < constant_pool->count_of_code_ptr_entries(); i++) { - int index = constant_pool->first_code_ptr_index() + i; - Address code_entry = - reinterpret_cast
(constant_pool->RawFieldOfElementAt(index)); + ConstantPoolArray* array = ConstantPoolArray::cast(object); + ConstantPoolArray::Iterator code_iter(array, ConstantPoolArray::CODE_PTR); + while (!code_iter.is_finished()) { + Address code_entry = reinterpret_cast
( + array->RawFieldOfElementAt(code_iter.next_index())); StaticVisitor::VisitCodeEntry(heap, code_entry); } - for (int i = 0; i < constant_pool->count_of_heap_ptr_entries(); i++) { - int index = constant_pool->first_heap_ptr_index() + i; - Object** slot = constant_pool->RawFieldOfElementAt(index); + + ConstantPoolArray::Iterator heap_iter(array, ConstantPoolArray::HEAP_PTR); + while (!heap_iter.is_finished()) { + Object** slot = array->RawFieldOfElementAt(heap_iter.next_index()); HeapObject* object = HeapObject::cast(*slot); heap->mark_compact_collector()->RecordSlot(slot, slot, object); bool is_weak_object = - (constant_pool->get_weak_object_state() == + (array->get_weak_object_state() == ConstantPoolArray::WEAK_OBJECTS_IN_OPTIMIZED_CODE && Code::IsWeakObjectInOptimizedCode(object)) || - (constant_pool->get_weak_object_state() == + (array->get_weak_object_state() == ConstantPoolArray::WEAK_OBJECTS_IN_IC && Code::IsWeakObjectInIC(object)); if (!is_weak_object) { diff --git a/src/objects.cc b/src/objects.cc index 38d4bd1..ddd97c6 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -9863,13 +9863,36 @@ bool Map::EquivalentToForNormalization(Map* other, void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) { - for (int i = 0; i < count_of_code_ptr_entries(); i++) { - int index = first_code_ptr_index() + i; - v->VisitCodeEntry(reinterpret_cast
(RawFieldOfElementAt(index))); + ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR); + while (!code_iter.is_finished()) { + v->VisitCodeEntry(reinterpret_cast
( + RawFieldOfElementAt(code_iter.next_index()))); } - for (int i = 0; i < count_of_heap_ptr_entries(); i++) { - int index = first_heap_ptr_index() + i; - v->VisitPointer(RawFieldOfElementAt(index)); + + ConstantPoolArray::Iterator heap_iter(this, ConstantPoolArray::HEAP_PTR); + while (!heap_iter.is_finished()) { + v->VisitPointer(RawFieldOfElementAt(heap_iter.next_index())); + } +} + + +void ConstantPoolArray::ClearPtrEntries(Isolate* isolate) { + Type type[] = { CODE_PTR, HEAP_PTR }; + Address default_value[] = { + isolate->builtins()->builtin(Builtins::kIllegal)->entry(), + reinterpret_cast
(isolate->heap()->undefined_value()) }; + + for (int i = 0; i < 2; ++i) { + for (int s = 0; s <= final_section(); ++s) { + LayoutSection section = static_cast(s); + if (number_of_entries(type[i], section) > 0) { + int offset = OffsetOfElementAt(first_index(type[i], section)); + MemsetPointer( + reinterpret_cast(HeapObject::RawField(this, offset)), + default_value[i], + number_of_entries(type[i], section)); + } + } } } diff --git a/src/objects.h b/src/objects.h index 1a0c47a..bf7f67d 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3094,16 +3094,41 @@ class FixedDoubleArray: public FixedArrayBase { // ConstantPoolArray describes a fixed-sized array containing constant pool -// entires. -// The format of the pool is: -// [0]: Field holding the first index which is a raw code target pointer entry -// [1]: Field holding the first index which is a heap pointer entry -// [2]: Field holding the first index which is a int32 entry -// [3] ... [first_code_ptr_index() - 1] : 64 bit entries -// [first_code_ptr_index()] ... [first_heap_ptr_index() - 1] : code pointers -// [first_heap_ptr_index()] ... [first_int32_index() - 1] : heap pointers -// [first_int32_index()] ... [length - 1] : 32 bit entries -class ConstantPoolArray: public FixedArrayBase { +// entries. +// +// A ConstantPoolArray can be structured in two different ways depending upon +// whether it is extended or small. The is_extended_layout() method can be used +// to discover which layout the constant pool has. +// +// The format of a small constant pool is: +// [kSmallLayout1Offset] : Small section layout bitmap 1 +// [kSmallLayout2Offset] : Small section layout bitmap 2 +// [first_index(INT64, SMALL_SECTION)] : 64 bit entries +// ... : ... +// [first_index(CODE_PTR, SMALL_SECTION)] : code pointer entries +// ... : ... +// [first_index(HEAP_PTR, SMALL_SECTION)] : heap pointer entries +// ... : ... +// [first_index(INT32, SMALL_SECTION)] : 32 bit entries +// ... : ... +// +// If the constant pool has an extended layout, the extended section constant +// pool also contains an extended section, which has the following format at +// location get_extended_section_header_offset(): +// [kExtendedInt64CountOffset] : count of extended 64 bit entries +// [kExtendedCodePtrCountOffset] : count of extended code pointers +// [kExtendedHeapPtrCountOffset] : count of extended heap pointers +// [kExtendedInt32CountOffset] : count of extended 32 bit entries +// [first_index(INT64, EXTENDED_SECTION)] : 64 bit entries +// ... : ... +// [first_index(CODE_PTR, EXTENDED_SECTION)]: code pointer entries +// ... : ... +// [first_index(HEAP_PTR, EXTENDED_SECTION)]: heap pointer entries +// ... : ... +// [first_index(INT32, EXTENDED_SECTION)] : 32 bit entries +// ... : ... +// +class ConstantPoolArray: public HeapObject { public: enum WeakObjectState { NO_WEAK_OBJECTS, @@ -3111,17 +3136,94 @@ class ConstantPoolArray: public FixedArrayBase { WEAK_OBJECTS_IN_IC }; - // Getters for the field storing the first index for different type entries. - inline int first_code_ptr_index(); - inline int first_heap_ptr_index(); - inline int first_int64_index(); - inline int first_int32_index(); + enum Type { + INT64 = 0, + CODE_PTR, + HEAP_PTR, + INT32, + // Number of types stored by the ConstantPoolArrays. + NUMBER_OF_TYPES, + FIRST_TYPE = INT64, + LAST_TYPE = INT32 + }; + + enum LayoutSection { + SMALL_SECTION = 0, + EXTENDED_SECTION + }; + + class NumberOfEntries BASE_EMBEDDED { + public: + inline NumberOfEntries(int int64_count, int code_ptr_count, + int heap_ptr_count, int int32_count) { + element_counts_[INT64] = int64_count; + element_counts_[CODE_PTR] = code_ptr_count; + element_counts_[HEAP_PTR] = heap_ptr_count; + element_counts_[INT32] = int32_count; + } + + inline NumberOfEntries(ConstantPoolArray* array, LayoutSection section) { + element_counts_[INT64] = array->number_of_entries(INT64, section); + element_counts_[CODE_PTR] = array->number_of_entries(CODE_PTR, section); + element_counts_[HEAP_PTR] = array->number_of_entries(HEAP_PTR, section); + element_counts_[INT32] = array->number_of_entries(INT32, section); + } + + inline int count_of(Type type) const { + ASSERT(type < NUMBER_OF_TYPES); + return element_counts_[type]; + } + + inline int total_count() const { + int count = 0; + for (int i = 0; i < NUMBER_OF_TYPES; i++) { + count += element_counts_[i]; + } + return count; + } + + inline int are_in_range(int min, int max) const { + for (int i = FIRST_TYPE; i < NUMBER_OF_TYPES; i++) { + if (element_counts_[i] < min || element_counts_[i] > max) { + return false; + } + } + return true; + } + + private: + int element_counts_[NUMBER_OF_TYPES]; + }; + + class Iterator BASE_EMBEDDED { + public: + inline Iterator(ConstantPoolArray* array, Type type) + : array_(array), type_(type), final_section_(array->final_section()) { + current_section_ = SMALL_SECTION; + next_index_ = array->first_index(type, SMALL_SECTION); + update_section(); + } + + inline int next_index(); + inline bool is_finished(); + private: + inline void update_section(); + ConstantPoolArray* array_; + const Type type_; + const LayoutSection final_section_; + + LayoutSection current_section_; + int next_index_; + }; + + // Getters for the first index, the last index and the count of entries of + // a given type for a given layout section. + inline int first_index(Type type, LayoutSection layout_section); + inline int last_index(Type type, LayoutSection layout_section); + inline int number_of_entries(Type type, LayoutSection layout_section); - // Getters for counts of different type entries. - inline int count_of_code_ptr_entries(); - inline int count_of_heap_ptr_entries(); - inline int count_of_int64_entries(); - inline int count_of_int32_entries(); + // Returns the type of the entry at the given index. + inline Type get_type(int index); // Setter and getter for pool elements. inline Address get_code_ptr_entry(int index); @@ -3130,49 +3232,98 @@ class ConstantPoolArray: public FixedArrayBase { inline int32_t get_int32_entry(int index); inline double get_int64_entry_as_double(int index); - // Setter and getter for weak objects state - inline void set_weak_object_state(WeakObjectState state); - inline WeakObjectState get_weak_object_state(); - inline void set(int index, Address value); inline void set(int index, Object* value); inline void set(int index, int64_t value); inline void set(int index, double value); inline void set(int index, int32_t value); - // Set up initial state. - inline void Init(int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries); + // Setter and getter for weak objects state + inline void set_weak_object_state(WeakObjectState state); + inline WeakObjectState get_weak_object_state(); + + // Returns true if the constant pool has an extended layout, false if it has + // only the small layout. + inline bool is_extended_layout(); + + // Returns the last LayoutSection in this constant pool array. + inline LayoutSection final_section(); + + // Set up initial state for a small layout constant pool array. + inline void Init(const NumberOfEntries& small); + + // Set up initial state for an extended layout constant pool array. + inline void InitExtended(const NumberOfEntries& small, + const NumberOfEntries& extended); + + // Clears the pointer entries with GC safe values. + void ClearPtrEntries(Isolate* isolate); + + // returns the total number of entries in the constant pool array. + inline int length(); // Garbage collection support. - inline static int SizeFor(int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries) { - return RoundUp(OffsetAt(number_of_int64_entries, - number_of_code_ptr_entries, - number_of_heap_ptr_entries, - number_of_int32_entries), - kPointerSize); + inline int size(); + + inline static int SizeFor(const NumberOfEntries& small) { + int size = kFirstEntryOffset + + (small.count_of(INT64) * kInt64Size) + + (small.count_of(CODE_PTR) * kPointerSize) + + (small.count_of(HEAP_PTR) * kPointerSize) + + (small.count_of(INT32) * kInt32Size); + return RoundUp(size, kPointerSize); + } + + inline static int SizeForExtended(const NumberOfEntries& small, + const NumberOfEntries& extended) { + int size = SizeFor(small); + size = RoundUp(size, kInt64Size); // Align extended header to 64 bits. + size += kExtendedFirstOffset + + (extended.count_of(INT64) * kInt64Size) + + (extended.count_of(CODE_PTR) * kPointerSize) + + (extended.count_of(HEAP_PTR) * kPointerSize) + + (extended.count_of(INT32) * kInt32Size); + return RoundUp(size, kPointerSize); + } + + inline static int entry_size(Type type) { + switch (type) { + case INT32: + return kInt32Size; + case INT64: + return kInt64Size; + case CODE_PTR: + case HEAP_PTR: + return kPointerSize; + default: + UNREACHABLE(); + return 0; + } } // Code Generation support. inline int OffsetOfElementAt(int index) { - ASSERT(index < length()); - if (index >= first_int32_index()) { - return OffsetAt(count_of_int64_entries(), count_of_code_ptr_entries(), - count_of_heap_ptr_entries(), index - first_int32_index()); - } else if (index >= first_heap_ptr_index()) { - return OffsetAt(count_of_int64_entries(), count_of_code_ptr_entries(), - index - first_heap_ptr_index(), 0); - } else if (index >= first_code_ptr_index()) { - return OffsetAt(count_of_int64_entries(), index - first_code_ptr_index(), - 0, 0); + int offset; + LayoutSection section; + if (is_extended_layout() && index >= first_extended_section_index()) { + section = EXTENDED_SECTION; + offset = get_extended_section_header_offset() + kExtendedFirstOffset; } else { - return OffsetAt(index, 0, 0, 0); + section = SMALL_SECTION; + offset = kFirstEntryOffset; } + + // Add offsets for the preceding type sections. + ASSERT(index <= last_index(LAST_TYPE, section)); + for (Type type = FIRST_TYPE; index > last_index(type, section); + type = next_type(type)) { + offset += entry_size(type) * number_of_entries(type, section); + } + + // Add offset for the index in it's type. + Type type = get_type(index); + offset += entry_size(type) * (index - first_index(type, section)); + return offset; } // Casting. @@ -3183,17 +3334,37 @@ class ConstantPoolArray: public FixedArrayBase { return HeapObject::RawField(this, OffsetOfElementAt(index)); } - // Layout description. - static const int kArrayLayoutOffset = FixedArray::kHeaderSize; - static const int kFirstOffset = kArrayLayoutOffset + kPointerSize; - - static const int kFieldBitSize = 10; - static const int kMaxEntriesPerType = (1 << kFieldBitSize) - 1; - - class NumberOfInt64EntriesField: public BitField {}; - class NumberOfCodePtrEntriesField: public BitField {}; - class NumberOfHeapPtrEntriesField: public BitField {}; - class WeakObjectStateField: public BitField {}; + // Small Layout description. + static const int kSmallLayout1Offset = HeapObject::kHeaderSize; + static const int kSmallLayout2Offset = kSmallLayout1Offset + kInt32Size; + static const int kHeaderSize = kSmallLayout2Offset + kInt32Size; + static const int kFirstEntryOffset = ROUND_UP(kHeaderSize, kInt64Size); + + static const int kSmallLayoutCountBits = 10; + static const int kMaxSmallEntriesPerType = (1 << kSmallLayoutCountBits) - 1; + + // Fields in kSmallLayout1Offset. + class Int64CountField: public BitField {}; + class CodePtrCountField: public BitField {}; + class HeapPtrCountField: public BitField {}; + class IsExtendedField: public BitField {}; + + // Fields in kSmallLayout2Offset. + class Int32CountField: public BitField {}; + class TotalCountField: public BitField {}; + class WeakObjectStateField: public BitField {}; + + // Extended layout description, which starts at + // get_extended_section_header_offset(). + static const int kExtendedInt64CountOffset = 0; + static const int kExtendedCodePtrCountOffset = + kExtendedInt64CountOffset + kPointerSize; + static const int kExtendedHeapPtrCountOffset = + kExtendedCodePtrCountOffset + kPointerSize; + static const int kExtendedInt32CountOffset = + kExtendedHeapPtrCountOffset + kPointerSize; + static const int kExtendedFirstOffset = + kExtendedInt32CountOffset + kPointerSize; // Dispatched behavior. void ConstantPoolIterateBody(ObjectVisitor* v); @@ -3202,15 +3373,13 @@ class ConstantPoolArray: public FixedArrayBase { DECLARE_VERIFIER(ConstantPoolArray) private: - inline static int OffsetAt(int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries) { - return kFirstOffset - + (number_of_int64_entries * kInt64Size) - + (number_of_code_ptr_entries * kPointerSize) - + (number_of_heap_ptr_entries * kPointerSize) - + (number_of_int32_entries * kInt32Size); + inline int first_extended_section_index(); + inline int get_extended_section_header_offset(); + + inline static Type next_type(Type type) { + ASSERT(type >= FIRST_TYPE && type < NUMBER_OF_TYPES); + int type_int = static_cast(type); + return static_cast(++type_int); } DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray); diff --git a/test/cctest/test-constantpool.cc b/test/cctest/test-constantpool.cc index f26c84f..67767a2 100644 --- a/test/cctest/test-constantpool.cc +++ b/test/cctest/test-constantpool.cc @@ -10,6 +10,14 @@ using namespace v8::internal; +static ConstantPoolArray::Type kTypes[] = { ConstantPoolArray::INT64, + ConstantPoolArray::CODE_PTR, + ConstantPoolArray::HEAP_PTR, + ConstantPoolArray::INT32 }; +static ConstantPoolArray::LayoutSection kSmall = + ConstantPoolArray::SMALL_SECTION; +static ConstantPoolArray::LayoutSection kExtended = + ConstantPoolArray::EXTENDED_SECTION; Code* DummyCode(LocalContext* context) { CompileRun("function foo() {};"); @@ -20,7 +28,7 @@ Code* DummyCode(LocalContext* context) { } -TEST(ConstantPool) { +TEST(ConstantPoolSmall) { LocalContext context; Isolate* isolate = CcTest::i_isolate(); Heap* heap = isolate->heap(); @@ -28,16 +36,18 @@ TEST(ConstantPool) { v8::HandleScope scope(context->GetIsolate()); // Check construction. - Handle array = factory->NewConstantPoolArray(3, 1, 2, 1); - CHECK_EQ(array->count_of_int64_entries(), 3); - CHECK_EQ(array->count_of_code_ptr_entries(), 1); - CHECK_EQ(array->count_of_heap_ptr_entries(), 2); - CHECK_EQ(array->count_of_int32_entries(), 1); - CHECK_EQ(array->length(), 7); - CHECK_EQ(array->first_int64_index(), 0); - CHECK_EQ(array->first_code_ptr_index(), 3); - CHECK_EQ(array->first_heap_ptr_index(), 4); - CHECK_EQ(array->first_int32_index(), 6); + ConstantPoolArray::NumberOfEntries small(3, 1, 2, 1); + Handle array = factory->NewConstantPoolArray(small); + + int expected_counts[] = { 3, 1, 2, 1 }; + int expected_first_idx[] = { 0, 3, 4, 6 }; + int expected_last_idx[] = { 2, 3, 5, 6 }; + for (int i = 0; i < 4; i++) { + CHECK_EQ(expected_counts[i], array->number_of_entries(kTypes[i], kSmall)); + CHECK_EQ(expected_first_idx[i], array->first_index(kTypes[i], kSmall)); + CHECK_EQ(expected_last_idx[i], array->last_index(kTypes[i], kSmall)); + } + CHECK(!array->is_extended_layout()); // Check getters and setters. int64_t big_number = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0); @@ -50,13 +60,13 @@ TEST(ConstantPool) { array->set(4, code); array->set(5, *object); array->set(6, 50); - CHECK_EQ(array->get_int64_entry(0), big_number); - CHECK_EQ(array->get_int64_entry_as_double(1), 0.5); - CHECK_EQ(array->get_int64_entry_as_double(2), 3e-24); - CHECK_EQ(array->get_code_ptr_entry(3), code->entry()); - CHECK_EQ(array->get_heap_ptr_entry(4), code); - CHECK_EQ(array->get_heap_ptr_entry(5), *object); - CHECK_EQ(array->get_int32_entry(6), 50); + CHECK_EQ(big_number, array->get_int64_entry(0)); + CHECK_EQ(0.5, array->get_int64_entry_as_double(1)); + CHECK_EQ(3e-24, array->get_int64_entry_as_double(2)); + CHECK_EQ(code->entry(), array->get_code_ptr_entry(3)); + CHECK_EQ(code, array->get_heap_ptr_entry(4)); + CHECK_EQ(*object, array->get_heap_ptr_entry(5)); + CHECK_EQ(50, array->get_int32_entry(6)); // Check pointers are updated on GC. Object* old_ptr = array->get_heap_ptr_entry(5); @@ -66,3 +76,169 @@ TEST(ConstantPool) { CHECK_NE(*object, old_ptr); CHECK_EQ(*object, new_ptr); } + + +TEST(ConstantPoolExtended) { + LocalContext context; + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + Factory* factory = isolate->factory(); + v8::HandleScope scope(context->GetIsolate()); + + // Check construction. + ConstantPoolArray::NumberOfEntries small(1, 2, 3, 4); + ConstantPoolArray::NumberOfEntries extended(5, 6, 7, 8); + Handle array = + factory->NewExtendedConstantPoolArray(small, extended); + + // Check small section. + int small_counts[] = { 1, 2, 3, 4 }; + int small_first_idx[] = { 0, 1, 3, 6 }; + int small_last_idx[] = { 0, 2, 5, 9 }; + for (int i = 0; i < 4; i++) { + CHECK_EQ(small_counts[i], array->number_of_entries(kTypes[i], kSmall)); + CHECK_EQ(small_first_idx[i], array->first_index(kTypes[i], kSmall)); + CHECK_EQ(small_last_idx[i], array->last_index(kTypes[i], kSmall)); + } + + // Check extended layout. + CHECK(array->is_extended_layout()); + int extended_counts[] = { 5, 6, 7, 8 }; + int extended_first_idx[] = { 10, 15, 21, 28 }; + int extended_last_idx[] = { 14, 20, 27, 35 }; + for (int i = 0; i < 4; i++) { + CHECK_EQ(extended_counts[i], + array->number_of_entries(kTypes[i], kExtended)); + CHECK_EQ(extended_first_idx[i], array->first_index(kTypes[i], kExtended)); + CHECK_EQ(extended_last_idx[i], array->last_index(kTypes[i], kExtended)); + } + + // Check small and large section's don't overlap. + int64_t small_section_int64 = V8_2PART_UINT64_C(0x56781234, DEF09ABC); + Code* small_section_code_ptr = DummyCode(&context); + Handle small_section_heap_ptr = factory->NewHeapNumber(4.0); + int32_t small_section_int32 = 0xab12cd45; + + int64_t extended_section_int64 = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0); + Code* extended_section_code_ptr = DummyCode(&context); + Handle extended_section_heap_ptr = factory->NewHeapNumber(4.0); + int32_t extended_section_int32 = 0xef67ab89; + + for (int i = array->first_index(ConstantPoolArray::INT64, kSmall); + i <= array->last_index(ConstantPoolArray::INT32, kSmall); i++) { + if (i <= array->last_index(ConstantPoolArray::INT64, kSmall)) { + array->set(i, small_section_int64); + } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kSmall)) { + array->set(i, small_section_code_ptr->entry()); + } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kSmall)) { + array->set(i, *small_section_heap_ptr); + } else { + CHECK(i <= array->last_index(ConstantPoolArray::INT32, kSmall)); + array->set(i, small_section_int32); + } + } + for (int i = array->first_index(ConstantPoolArray::INT64, kExtended); + i <= array->last_index(ConstantPoolArray::INT32, kExtended); i++) { + if (i <= array->last_index(ConstantPoolArray::INT64, kExtended)) { + array->set(i, extended_section_int64); + } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kExtended)) { + array->set(i, extended_section_code_ptr->entry()); + } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kExtended)) { + array->set(i, *extended_section_heap_ptr); + } else { + CHECK(i <= array->last_index(ConstantPoolArray::INT32, kExtended)); + array->set(i, extended_section_int32); + } + } + + for (int i = array->first_index(ConstantPoolArray::INT64, kSmall); + i <= array->last_index(ConstantPoolArray::INT32, kSmall); i++) { + if (i <= array->last_index(ConstantPoolArray::INT64, kSmall)) { + CHECK_EQ(small_section_int64, array->get_int64_entry(i)); + } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kSmall)) { + CHECK_EQ(small_section_code_ptr->entry(), array->get_code_ptr_entry(i)); + } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kSmall)) { + CHECK_EQ(*small_section_heap_ptr, array->get_heap_ptr_entry(i)); + } else { + CHECK(i <= array->last_index(ConstantPoolArray::INT32, kSmall)); + CHECK_EQ(small_section_int32, array->get_int32_entry(i)); + } + } + for (int i = array->first_index(ConstantPoolArray::INT64, kExtended); + i <= array->last_index(ConstantPoolArray::INT32, kExtended); i++) { + if (i <= array->last_index(ConstantPoolArray::INT64, kExtended)) { + CHECK_EQ(extended_section_int64, array->get_int64_entry(i)); + } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kExtended)) { + CHECK_EQ(extended_section_code_ptr->entry(), + array->get_code_ptr_entry(i)); + } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kExtended)) { + CHECK_EQ(*extended_section_heap_ptr, array->get_heap_ptr_entry(i)); + } else { + CHECK(i <= array->last_index(ConstantPoolArray::INT32, kExtended)); + CHECK_EQ(extended_section_int32, array->get_int32_entry(i)); + } + } + // Check pointers are updated on GC in extended section. + int index = array->first_index(ConstantPoolArray::HEAP_PTR, kExtended); + Object* old_ptr = array->get_heap_ptr_entry(index); + CHECK_EQ(*extended_section_heap_ptr, old_ptr); + heap->CollectGarbage(NEW_SPACE); + Object* new_ptr = array->get_heap_ptr_entry(index); + CHECK_NE(*extended_section_heap_ptr, old_ptr); + CHECK_EQ(*extended_section_heap_ptr, new_ptr); +} + + +static void CheckIterator(Handle array, + ConstantPoolArray::Type type, + int expected_indexes[], + int count) { + int i = 0; + ConstantPoolArray::Iterator iter(*array, type); + while (!iter.is_finished()) { + CHECK_EQ(expected_indexes[i++], iter.next_index()); + } + CHECK_EQ(count, i); +} + + +TEST(ConstantPoolIteratorSmall) { + LocalContext context; + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); + v8::HandleScope scope(context->GetIsolate()); + + ConstantPoolArray::NumberOfEntries small(1, 5, 2, 0); + Handle array = factory->NewConstantPoolArray(small); + + int expected_int64_indexs[] = { 0 }; + CheckIterator(array, ConstantPoolArray::INT64, expected_int64_indexs, 1); + int expected_code_indexs[] = { 1, 2, 3, 4, 5 }; + CheckIterator(array, ConstantPoolArray::CODE_PTR, expected_code_indexs, 5); + int expected_heap_indexs[] = { 6, 7 }; + CheckIterator(array, ConstantPoolArray::HEAP_PTR, expected_heap_indexs, 2); + int expected_int32_indexs[1]; + CheckIterator(array, ConstantPoolArray::INT32, expected_int32_indexs, 0); +} + + +TEST(ConstantPoolIteratorExtended) { + LocalContext context; + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); + v8::HandleScope scope(context->GetIsolate()); + + ConstantPoolArray::NumberOfEntries small(1, 0, 0, 4); + ConstantPoolArray::NumberOfEntries extended(5, 0, 3, 0); + Handle array = + factory->NewExtendedConstantPoolArray(small, extended); + + int expected_int64_indexs[] = { 0, 5, 6, 7, 8, 9 }; + CheckIterator(array, ConstantPoolArray::INT64, expected_int64_indexs, 6); + int expected_code_indexs[1]; + CheckIterator(array, ConstantPoolArray::CODE_PTR, expected_code_indexs, 0); + int expected_heap_indexs[] = { 10, 11, 12 }; + CheckIterator(array, ConstantPoolArray::HEAP_PTR, expected_heap_indexs, 3); + int expected_int32_indexs[] = { 1, 2, 3, 4 }; + CheckIterator(array, ConstantPoolArray::INT32, expected_int32_indexs, 4); +}