Index: src/arm/assembler-arm.cc |
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc |
index b90ff1e05b6a383cbf40276af1e762b20ebd2635..74c682a47f60799b4fecc7cbf56a7f99bddb0dce 100644 |
--- a/src/arm/assembler-arm.cc |
+++ b/src/arm/assembler-arm.cc |
@@ -3734,18 +3734,19 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
// the gap to the relocation information). |
int jump_instr = require_jump ? kInstrSize : 0; |
int size_up_to_marker = jump_instr + kInstrSize; |
- int size_after_marker = num_pending_32_bit_constants_ * kPointerSize; |
+ int estimated_size_after_marker = |
+ num_pending_32_bit_constants_ * kPointerSize; |
bool has_fp_values = (num_pending_64_bit_constants_ > 0); |
bool require_64_bit_align = false; |
if (has_fp_values) { |
- require_64_bit_align = (((uintptr_t)pc_ + size_up_to_marker) & 0x7); |
+ require_64_bit_align = IsAligned( |
+ reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), kDoubleAlignment); |
if (require_64_bit_align) { |
- size_after_marker += kInstrSize; |
+ estimated_size_after_marker += kInstrSize; |
} |
- size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; |
+ estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; |
} |
- |
- int size = size_up_to_marker + size_after_marker; |
+ int estimated_size = size_up_to_marker + estimated_size_after_marker; |
// We emit a constant pool when: |
// * requested to do so by parameter force_emit (e.g. after each function). |
@@ -3759,7 +3760,7 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0)); |
bool need_emit = false; |
if (has_fp_values) { |
- int dist64 = pc_offset() + size - |
+ int dist64 = pc_offset() + estimated_size - |
num_pending_32_bit_constants_ * kPointerSize - |
first_const_pool_64_use_; |
if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || |
@@ -3767,8 +3768,7 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
need_emit = true; |
} |
} |
- int dist32 = |
- pc_offset() + size - first_const_pool_32_use_; |
+ int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_; |
if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || |
(!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { |
need_emit = true; |
@@ -3776,6 +3776,37 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
if (!need_emit) return; |
} |
+ // Deduplicate constants. |
+ int size_after_marker = estimated_size_after_marker; |
+ for (int i = 0; i < num_pending_64_bit_constants_; i++) { |
+ ConstantPoolEntry& entry = pending_64_bit_constants_[i]; |
+ DCHECK(!entry.is_merged()); |
+ for (int j = 0; j < i; j++) { |
+ if (entry.value64() == pending_64_bit_constants_[j].value64()) { |
+ DCHECK(!pending_64_bit_constants_[j].is_merged()); |
+ entry.set_merged_index(j); |
+ size_after_marker -= kDoubleSize; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ for (int i = 0; i < num_pending_32_bit_constants_; i++) { |
+ ConstantPoolEntry& entry = pending_32_bit_constants_[i]; |
+ DCHECK(!entry.is_merged()); |
+ if (!entry.sharing_ok()) continue; |
+ for (int j = 0; j < i; j++) { |
+ if (entry.value() == pending_32_bit_constants_[j].value()) { |
+ DCHECK(!pending_32_bit_constants_[j].is_merged()); |
+ entry.set_merged_index(j); |
rmcilroy
2015/07/03 08:58:04
I think this the wrong way round, you should be se
Yang
2015/07/03 09:07:33
I haven't changed the merge loop at all. j is neve
rmcilroy
2015/07/03 09:45:14
You're right, oops. I didn't look at the for loop
|
+ size_after_marker -= kPointerSize; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ int size = size_up_to_marker + size_after_marker; |
+ |
int needed_space = size + kGap; |
while (buffer_space() <= needed_space) GrowBuffer(); |
@@ -3785,6 +3816,9 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
RecordComment("[ Constant Pool"); |
RecordConstPool(size); |
+ Label size_check; |
+ bind(&size_check); |
+ |
// Emit jump over constant pool if necessary. |
Label after_pool; |
if (require_jump) { |
@@ -3805,8 +3839,6 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
for (int i = 0; i < num_pending_64_bit_constants_; i++) { |
ConstantPoolEntry& entry = pending_64_bit_constants_[i]; |
- DCHECK(!((uintptr_t)pc_ & 0x7)); // Check 64-bit alignment. |
- |
Instr instr = instr_at(entry.position()); |
// Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0. |
DCHECK((IsVldrDPcImmediateOffset(instr) && |
@@ -3815,24 +3847,19 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
int delta = pc_offset() - entry.position() - kPcLoadDelta; |
DCHECK(is_uint10(delta)); |
- bool found = false; |
- uint64_t value = entry.value64(); |
- for (int j = 0; j < i; j++) { |
- ConstantPoolEntry& entry2 = pending_64_bit_constants_[j]; |
- if (value == entry2.value64()) { |
- found = true; |
- Instr instr2 = instr_at(entry2.position()); |
- DCHECK(IsVldrDPcImmediateOffset(instr2)); |
- delta = GetVldrDRegisterImmediateOffset(instr2); |
- delta += entry2.position() - entry.position(); |
- break; |
- } |
+ if (entry.is_merged()) { |
+ ConstantPoolEntry& merged = |
+ pending_64_bit_constants_[entry.merged_index()]; |
+ DCHECK(entry.value64() == merged.value64()); |
+ Instr merged_instr = instr_at(merged.position()); |
+ DCHECK(IsVldrDPcImmediateOffset(merged_instr)); |
+ delta = GetVldrDRegisterImmediateOffset(merged_instr); |
+ delta += merged.position() - entry.position(); |
} |
- |
instr_at_put(entry.position(), |
SetVldrDRegisterImmediateOffset(instr, delta)); |
- |
- if (!found) { |
+ if (!entry.is_merged()) { |
+ DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment)); |
dq(entry.value64()); |
} |
} |
@@ -3844,41 +3871,31 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
// 64-bit loads shouldn't get here. |
DCHECK(!IsVldrDPcImmediateOffset(instr)); |
+ DCHECK(!IsMovW(instr)); |
+ DCHECK(IsLdrPcImmediateOffset(instr) && |
+ GetLdrRegisterImmediateOffset(instr) == 0); |
- if (IsLdrPcImmediateOffset(instr) && |
- GetLdrRegisterImmediateOffset(instr) == 0) { |
- int delta = pc_offset() - entry.position() - kPcLoadDelta; |
- DCHECK(is_uint12(delta)); |
- // 0 is the smallest delta: |
- // ldr rd, [pc, #0] |
- // constant pool marker |
- // data |
- |
- bool found = false; |
- if (entry.sharing_ok()) { |
- for (int j = 0; j < i; j++) { |
- ConstantPoolEntry& entry2 = pending_32_bit_constants_[j]; |
- |
- if (entry2.value() == entry.value()) { |
- Instr instr2 = instr_at(entry2.position()); |
- if (IsLdrPcImmediateOffset(instr2)) { |
- delta = GetLdrRegisterImmediateOffset(instr2); |
- delta += entry2.position() - entry.position(); |
- found = true; |
- break; |
- } |
- } |
- } |
- } |
- |
- instr_at_put(entry.position(), |
- SetLdrRegisterImmediateOffset(instr, delta)); |
- |
- if (!found) { |
- emit(entry.value()); |
- } |
- } else { |
- DCHECK(IsMovW(instr)); |
+ int delta = pc_offset() - entry.position() - kPcLoadDelta; |
+ DCHECK(is_uint12(delta)); |
+ // 0 is the smallest delta: |
+ // ldr rd, [pc, #0] |
+ // constant pool marker |
+ // data |
+ |
+ if (entry.is_merged()) { |
+ DCHECK(entry.sharing_ok()); |
+ ConstantPoolEntry& merged = |
+ pending_32_bit_constants_[entry.merged_index()]; |
+ DCHECK(entry.value() == merged.value()); |
+ Instr merged_instr = instr_at(merged.position()); |
+ DCHECK(IsLdrPcImmediateOffset(merged_instr)); |
+ delta = GetLdrRegisterImmediateOffset(merged_instr); |
+ delta += merged.position() - entry.position(); |
+ } |
+ instr_at_put(entry.position(), |
+ SetLdrRegisterImmediateOffset(instr, delta)); |
+ if (!entry.is_merged()) { |
+ emit(entry.value()); |
} |
} |
@@ -3889,6 +3906,8 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
RecordComment("]"); |
+ DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check)); |
+ |
if (after_pool.is_linked()) { |
bind(&after_pool); |
} |