Index: src/a64/assembler-a64.cc |
diff --git a/src/a64/assembler-a64.cc b/src/a64/assembler-a64.cc |
index 14f78a09c7a9279ed4e9ea1cdb11bccd3c75f5c4..a62a7c81ce128aa1c5805364cf4604d03616ff8a 100644 |
--- a/src/a64/assembler-a64.cc |
+++ b/src/a64/assembler-a64.cc |
@@ -624,6 +624,13 @@ void Assembler::ConstantPoolMarker(uint32_t size) { |
} |
+void Assembler::EmitPoolGuard() { |
+ // We must generate only one instruction as this is used in scopes that |
+ // control the size of the code generated. |
+ Emit(BLR | Rn(xzr)); |
+} |
+ |
+ |
void Assembler::ConstantPoolGuard() { |
#ifdef DEBUG |
// Currently this is only used after a constant pool marker. |
@@ -632,9 +639,7 @@ void Assembler::ConstantPoolGuard() { |
ASSERT(instr->preceding()->IsLdrLiteralX() && |
instr->preceding()->Rt() == xzr.code()); |
#endif |
- |
- // We must generate only one instruction. |
- Emit(BLR | Rn(xzr)); |
+ EmitPoolGuard(); |
} |
@@ -2427,13 +2432,15 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL); |
if (((rmode >= RelocInfo::JS_RETURN) && |
(rmode <= RelocInfo::DEBUG_BREAK_SLOT)) || |
- (rmode == RelocInfo::CONST_POOL)) { |
+ (rmode == RelocInfo::CONST_POOL) || |
+ (rmode == RelocInfo::VENEER_POOL)) { |
// Adjust code for new modes. |
ASSERT(RelocInfo::IsDebugBreakSlot(rmode) |
|| RelocInfo::IsJSReturn(rmode) |
|| RelocInfo::IsComment(rmode) |
|| RelocInfo::IsPosition(rmode) |
- || RelocInfo::IsConstPool(rmode)); |
+ || RelocInfo::IsConstPool(rmode) |
+ || RelocInfo::IsVeneerPool(rmode)); |
// These modes do not need an entry in the constant pool. |
} else { |
ASSERT(num_pending_reloc_info_ < kMaxNumPendingRelocInfo); |
@@ -2570,7 +2577,8 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
rinfo.rmode() != RelocInfo::POSITION && |
rinfo.rmode() != RelocInfo::STATEMENT_POSITION && |
- rinfo.rmode() != RelocInfo::CONST_POOL); |
+ rinfo.rmode() != RelocInfo::CONST_POOL && |
+ rinfo.rmode() != RelocInfo::VENEER_POOL); |
Instruction* instr = reinterpret_cast<Instruction*>(rinfo.pc()); |
// Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. |
@@ -2608,10 +2616,32 @@ bool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) { |
} |
+void Assembler::RecordVeneerPool(int location_offset, int size) { |
+#ifdef ENABLE_DEBUGGER_SUPPORT |
+ RelocInfo rinfo(buffer_ + location_offset, |
+ RelocInfo::VENEER_POOL, static_cast<intptr_t>(size), |
+ NULL); |
+ reloc_info_writer.Write(&rinfo); |
+#endif |
+} |
+ |
+ |
void Assembler::EmitVeneers(bool need_protection, int margin) { |
BlockPoolsScope scope(this); |
RecordComment("[ Veneers"); |
+ // The exact size of the veneer pool must be recorded (see the comment at the |
+ // declaration site of RecordConstPool()), but computing the number of |
+ // veneers that will be generated is not obvious. So instead we remember the |
+ // current position and will record the size after the pool has been |
+ // generated. |
+ Label size_check; |
+ bind(&size_check); |
+ int veneer_pool_relocinfo_loc = pc_offset(); |
+#ifdef DEBUG |
+ byte* reloc_writer_record_pos = reloc_info_writer.pos(); |
+#endif |
+ |
Label end; |
if (need_protection) { |
b(&end); |
@@ -2619,7 +2649,7 @@ void Assembler::EmitVeneers(bool need_protection, int margin) { |
EmitVeneersGuard(); |
- Label size_check; |
+ Label veneer_size_check; |
std::multimap<int, FarBranchInfo>::iterator it, it_to_delete; |
@@ -2630,7 +2660,7 @@ void Assembler::EmitVeneers(bool need_protection, int margin) { |
Label* label = it->second.label_; |
#ifdef DEBUG |
- bind(&size_check); |
+ bind(&veneer_size_check); |
#endif |
// Patch the branch to point to the current position, and emit a branch |
// to the label. |
@@ -2639,9 +2669,9 @@ void Assembler::EmitVeneers(bool need_protection, int margin) { |
branch->SetImmPCOffsetTarget(veneer); |
b(label); |
#ifdef DEBUG |
- ASSERT(SizeOfCodeGeneratedSince(&size_check) <= |
+ ASSERT(SizeOfCodeGeneratedSince(&veneer_size_check) <= |
static_cast<uint64_t>(kMaxVeneerCodeSize)); |
- size_check.Unuse(); |
+ veneer_size_check.Unuse(); |
#endif |
it_to_delete = it++; |
@@ -2651,6 +2681,11 @@ void Assembler::EmitVeneers(bool need_protection, int margin) { |
} |
} |
+ // Record the veneer pool size. |
+ ASSERT(reloc_writer_record_pos == reloc_info_writer.pos()); |
+ int pool_size = SizeOfCodeGeneratedSince(&size_check); |
+ RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size); |
+ |
if (unresolved_branches_.empty()) { |
next_veneer_pool_check_ = kMaxInt; |
} else { |
@@ -2664,13 +2699,6 @@ void Assembler::EmitVeneers(bool need_protection, int margin) { |
} |
-void Assembler::EmitVeneersGuard() { |
- if (emit_debug_code()) { |
- Unreachable(); |
- } |
-} |
- |
- |
void Assembler::CheckVeneerPool(bool require_jump, |
int margin) { |
// There is nothing to do if there are no pending veneer pool entries. |