Calling OffsetOfElementAt becomes expensive when compiling functions with many
constant pool entries. This was causing a regression in MandreelLatency due
to the time spent populating the constant pool array for large compiled
functions.
This change avoids calling OffsetOfElementAt for each entry, and instead keeps
track of the current offsets in ConstantPoolBuilder::Populate. This gives the
following improvements on a Nexus 5:
Inline CP | OOL CP (before CL) | OOL CP (after CL)
Mandreel: 4305 | 3961 | 4120
MandreelLatency: 2298 | 1198 | 1994
Octane Score: 5197 | 4982 | 5152
R=ulan@chromium.org
Review URL: https://codereview.chromium.org/
376973002
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22293
ce2b1a6d-e550-0410-aec6-
3dcde31c8c00
rmode != RelocInfo::STATEMENT_POSITION &&
rmode != RelocInfo::CONST_POOL);
-
// Try to merge entries which won't be patched.
int merged_index = -1;
ConstantPoolArray::LayoutSection entry_section = current_section_;
constant_pool, ConstantPoolArray::EXTENDED_SECTION)));
}
- ConstantPoolArray::NumberOfEntries small_idx;
- ConstantPoolArray::NumberOfEntries extended_idx;
+ // Set up initial offsets.
+ int offsets[ConstantPoolArray::NUMBER_OF_LAYOUT_SECTIONS]
+ [ConstantPoolArray::NUMBER_OF_TYPES];
+ for (int section = 0; section <= constant_pool->final_section(); section++) {
+ int section_start = (section == ConstantPoolArray::EXTENDED_SECTION)
+ ? small_entries()->total_count()
+ : 0;
+ for (int i = 0; i < ConstantPoolArray::NUMBER_OF_TYPES; i++) {
+ ConstantPoolArray::Type type = static_cast<ConstantPoolArray::Type>(i);
+ if (number_of_entries_[section].count_of(type) != 0) {
+ offsets[section][type] = constant_pool->OffsetOfElementAt(
+ number_of_entries_[section].base_of(type) + section_start);
+ }
+ }
+ }
+
for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin();
entry != entries_.end(); entry++) {
RelocInfo rinfo = entry->rinfo_;
// Update constant pool if necessary and get the entry's offset.
int offset;
if (entry->merged_index_ == -1) {
- int index;
- if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) {
- index = small_entries()->total_count() +
- extended_entries()->base_of(type) + extended_idx.count_of(type);
- extended_idx.increment(type);
- } else {
- ASSERT(entry->section_ == ConstantPoolArray::SMALL_SECTION);
- index = small_entries()->base_of(type) + small_idx.count_of(type);
- small_idx.increment(type);
- }
+ offset = offsets[entry->section_][type];
+ offsets[entry->section_][type] += ConstantPoolArray::entry_size(type);
if (type == ConstantPoolArray::INT64) {
- constant_pool->set(index, rinfo.data64());
+ constant_pool->set_at_offset(offset, rinfo.data64());
} else if (type == ConstantPoolArray::INT32) {
- constant_pool->set(index, static_cast<int32_t>(rinfo.data()));
+ constant_pool->set_at_offset(offset, rinfo.data());
} else if (type == ConstantPoolArray::CODE_PTR) {
- constant_pool->set(index, reinterpret_cast<Address>(rinfo.data()));
+ constant_pool->set_at_offset(offset,
+ reinterpret_cast<Address>(rinfo.data()));
} else {
ASSERT(type == ConstantPoolArray::HEAP_PTR);
- constant_pool->set(index, reinterpret_cast<Object*>(rinfo.data()));
+ constant_pool->set_at_offset(offset,
+ reinterpret_cast<Object*>(rinfo.data()));
}
- offset = constant_pool->OffsetOfElementAt(index) - kHeapObjectTag;
+ offset -= kHeapObjectTag;
entry->merged_index_ = offset; // Stash offset for merged entries.
} else {
ASSERT(entry->merged_index_ < (entry - entries_.begin()));
rinfo.pc(), Assembler::SetLdrRegisterImmediateOffset(instr, offset));
}
}
-
- ASSERT(small_idx.equals(*small_entries()));
- ASSERT(extended_idx.equals(*extended_entries()));
}
}
+bool ConstantPoolArray::offset_is_type(int offset, Type type) {
+ return (offset >= OffsetOfElementAt(first_index(type, SMALL_SECTION)) &&
+ offset <= OffsetOfElementAt(last_index(type, SMALL_SECTION))) ||
+ (is_extended_layout() &&
+ offset >= OffsetOfElementAt(first_index(type, EXTENDED_SECTION)) &&
+ offset <= OffsetOfElementAt(last_index(type, EXTENDED_SECTION)));
+}
+
+
ConstantPoolArray::Type ConstantPoolArray::get_type(int index) {
LayoutSection section;
if (is_extended_layout() && index >= first_extended_section_index()) {
}
+void ConstantPoolArray::set_at_offset(int offset, int32_t value) {
+ ASSERT(map() == GetHeap()->constant_pool_array_map());
+ ASSERT(offset_is_type(offset, INT32));
+ WRITE_INT32_FIELD(this, offset, value);
+}
+
+
+void ConstantPoolArray::set_at_offset(int offset, int64_t value) {
+ ASSERT(map() == GetHeap()->constant_pool_array_map());
+ ASSERT(offset_is_type(offset, INT64));
+ WRITE_INT64_FIELD(this, offset, value);
+}
+
+
+void ConstantPoolArray::set_at_offset(int offset, double value) {
+ ASSERT(map() == GetHeap()->constant_pool_array_map());
+ ASSERT(offset_is_type(offset, INT64));
+ WRITE_DOUBLE_FIELD(this, offset, value);
+}
+
+
+void ConstantPoolArray::set_at_offset(int offset, Address value) {
+ ASSERT(map() == GetHeap()->constant_pool_array_map());
+ ASSERT(offset_is_type(offset, CODE_PTR));
+ WRITE_FIELD(this, offset, reinterpret_cast<Object*>(value));
+ WRITE_BARRIER(GetHeap(), this, offset, reinterpret_cast<Object*>(value));
+}
+
+
+void ConstantPoolArray::set_at_offset(int offset, Object* value) {
+ ASSERT(map() == GetHeap()->constant_pool_array_map());
+ ASSERT(offset_is_type(offset, HEAP_PTR));
+ WRITE_FIELD(this, offset, value);
+ WRITE_BARRIER(GetHeap(), this, offset, value);
+}
+
+
void ConstantPoolArray::Init(const NumberOfEntries& small) {
uint32_t small_layout_1 =
Int64CountField::encode(small.count_of(INT64)) |
enum LayoutSection {
SMALL_SECTION = 0,
- EXTENDED_SECTION
+ EXTENDED_SECTION,
+ NUMBER_OF_LAYOUT_SECTIONS
};
class NumberOfEntries BASE_EMBEDDED {
// Returns the type of the entry at the given index.
inline Type get_type(int index);
+ inline bool offset_is_type(int offset, Type type);
// Setter and getter for pool elements.
inline Address get_code_ptr_entry(int index);
inline void set(int index, double value);
inline void set(int index, int32_t value);
+ // Setters which take a raw offset rather than an index (for code generation).
+ inline void set_at_offset(int offset, int32_t value);
+ inline void set_at_offset(int offset, int64_t value);
+ inline void set_at_offset(int offset, double value);
+ inline void set_at_offset(int offset, Address value);
+ inline void set_at_offset(int offset, Object* value);
+
// Setter and getter for weak objects state
inline void set_weak_object_state(WeakObjectState state);
inline WeakObjectState get_weak_object_state();