Add support for extended constant pool arrays.
authorrmcilroy@chromium.org <rmcilroy@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 3 Jun 2014 16:22:10 +0000 (16:22 +0000)
committerrmcilroy@chromium.org <rmcilroy@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 3 Jun 2014 16:22:10 +0000 (16:22 +0000)
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

13 files changed:
src/arm/assembler-arm.cc
src/factory.cc
src/factory.h
src/heap.cc
src/heap.h
src/mark-compact.cc
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects-visiting-inl.h
src/objects.cc
src/objects.h
test/cctest/test-constantpool.cc

index a71bfca..ee4def9 100644 (file)
@@ -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<ConstantPoolArray> 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<Object *>(rinfo->data()));
+                           reinterpret_cast<Address>(rinfo->data()));
       } else {
         ASSERT(IsHeapPtrEntry(rmode));
         offset = constant_pool->OffsetOfElementAt(index_heap_ptr) -
index 537ca17..33d856f 100644 (file)
@@ -115,18 +115,23 @@ Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(
 
 
 Handle<ConstantPoolArray> 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<ConstantPoolArray> 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);
 }
 
index 0513ac5..7ef8911 100644 (file)
@@ -45,10 +45,11 @@ class Factory V8_FINAL {
       PretenureFlag pretenure = NOT_TENURED);
 
   Handle<ConstantPoolArray> 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<ConstantPoolArray> NewExtendedConstantPoolArray(
+      const ConstantPoolArray::NumberOfEntries& small,
+      const ConstantPoolArray::NumberOfEntries& extended);
 
   Handle<OrderedHashSet> NewOrderedHashSet();
   Handle<OrderedHashMap> NewOrderedHashMap();
index fce6bf8..7c1d61a 100644 (file)
@@ -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<Address*>(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;
 }
 
index 3945515..549c03f 100644 (file)
@@ -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(
index 32aba56..1e1a737 100644 (file)
@@ -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()) {
index 5ce04b9..762354e 100644 (file)
@@ -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()));
   }
 }
 
index 872fa1c..36d1aa1 100644 (file)
@@ -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<Address>(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<Object*>(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<FixedDoubleArray*>(this)->length());
   }
   if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
-    return ConstantPoolArray::SizeFor(
-        reinterpret_cast<ConstantPoolArray*>(this)->count_of_int64_entries(),
-        reinterpret_cast<ConstantPoolArray*>(this)->count_of_code_ptr_entries(),
-        reinterpret_cast<ConstantPoolArray*>(this)->count_of_heap_ptr_entries(),
-        reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
+    return reinterpret_cast<ConstantPoolArray*>(this)->size();
   }
   if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
       instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
index 6595acc..c51c04e 100644 (file)
@@ -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<void*>(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<void*>(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<void*>(get_code_ptr_entry(i)));
+    } else if (i <= last_index(HEAP_PTR, EXTENDED_SECTION)) {
+      PrintF(out, "\n  [%d]: heap pointer: %p", i,
+             reinterpret_cast<void*>(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");
 }
 
index 057b8ae..d5681b8 100644 (file)
@@ -498,23 +498,24 @@ template<typename StaticVisitor>
 void StaticMarkingVisitor<StaticVisitor>::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<Address>(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<Address>(
+        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) {
index 38d4bd1..ddd97c6 100644 (file)
@@ -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<Address>(RawFieldOfElementAt(index)));
+  ConstantPoolArray::Iterator code_iter(this, ConstantPoolArray::CODE_PTR);
+  while (!code_iter.is_finished()) {
+    v->VisitCodeEntry(reinterpret_cast<Address>(
+        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<Address>(isolate->heap()->undefined_value()) };
+
+  for (int i = 0; i < 2; ++i) {
+    for (int s = 0; s <= final_section(); ++s) {
+      LayoutSection section = static_cast<LayoutSection>(s);
+      if (number_of_entries(type[i], section) > 0) {
+        int offset = OffsetOfElementAt(first_index(type[i], section));
+        MemsetPointer(
+          reinterpret_cast<Address*>(HeapObject::RawField(this, offset)),
+          default_value[i],
+          number_of_entries(type[i], section));
+      }
+    }
   }
 }
 
index 1a0c47a..bf7f67d 100644 (file)
@@ -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<int, 0, kFieldBitSize> {};
-  class NumberOfCodePtrEntriesField: public BitField<int, 10, kFieldBitSize> {};
-  class NumberOfHeapPtrEntriesField: public BitField<int, 20, kFieldBitSize> {};
-  class WeakObjectStateField: public BitField<WeakObjectState, 30, 2> {};
+  // 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<int, 1, kSmallLayoutCountBits> {};
+  class CodePtrCountField: public BitField<int, 11, kSmallLayoutCountBits> {};
+  class HeapPtrCountField: public BitField<int, 21, kSmallLayoutCountBits> {};
+  class IsExtendedField: public BitField<bool, 31, 1> {};
+
+  // Fields in kSmallLayout2Offset.
+  class Int32CountField: public BitField<int, 1, kSmallLayoutCountBits> {};
+  class TotalCountField: public BitField<int, 11, 12> {};
+  class WeakObjectStateField: public BitField<WeakObjectState, 23, 2> {};
+
+  // 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<int>(type);
+    return static_cast<Type>(++type_int);
   }
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray);
index f26c84f..67767a2 100644 (file)
 
 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<ConstantPoolArray> 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<ConstantPoolArray> 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<ConstantPoolArray> 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<Object> 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<Object> 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<ConstantPoolArray> 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<ConstantPoolArray> 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<ConstantPoolArray> 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);
+}