| 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.
|
|
|