diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index 7a6155f2e8..fbe8e99597 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -492,6 +492,7 @@ Assembler::~Assembler() { void Assembler::GetCode(CodeDesc* desc) { + reloc_info_writer.Finish(); if (!FLAG_enable_ool_constant_pool) { // Emit constant pool if necessary. CheckConstPool(true, false); diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc index f34b419570..78cbdff2be 100644 --- a/src/arm64/assembler-arm64.cc +++ b/src/arm64/assembler-arm64.cc @@ -590,6 +590,7 @@ void Assembler::Reset() { void Assembler::GetCode(CodeDesc* desc) { + reloc_info_writer.Finish(); // Emit constant pool if necessary. CheckConstPool(true, false); DCHECK(constpool_.IsEmpty()); diff --git a/src/assembler.cc b/src/assembler.cc index 4c5eda1981..56578ca563 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -415,7 +415,38 @@ void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) { } +void RelocInfoWriter::WritePosition(int pc_delta, int pos_delta, + RelocInfo::Mode rmode) { + int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag + : kStatementPositionTag; + // Check if delta is small enough to fit in a tagged byte. + if (is_intn(pos_delta, kSmallDataBits)) { + WriteTaggedPC(pc_delta, kLocatableTag); + WriteTaggedData(pos_delta, pos_type_tag); + } else { + // Otherwise, use costly encoding. + WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag); + WriteExtraTaggedIntData(pos_delta, pos_type_tag); + } +} + + +void RelocInfoWriter::FlushPosition() { + if (!next_position_candidate_flushed_) { + WritePosition(next_position_candidate_pc_delta_, + next_position_candidate_pos_delta_, RelocInfo::POSITION); + next_position_candidate_pos_delta_ = 0; + next_position_candidate_pc_delta_ = 0; + next_position_candidate_flushed_ = true; + } +} + + void RelocInfoWriter::Write(const RelocInfo* rinfo) { + RelocInfo::Mode rmode = rinfo->rmode(); + if (rmode != RelocInfo::POSITION) { + FlushPosition(); + } #ifdef DEBUG byte* begin_pos = pos_; #endif @@ -425,7 +456,6 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) { <= kMaxStandardNonCompactModes); // Use unsigned delta-encoding for pc. uint32_t pc_delta = static_cast(rinfo->pc() - last_pc_); - RelocInfo::Mode rmode = rinfo->rmode(); // The two most common modes are given small tags, and usually fit in a byte. if (rmode == RelocInfo::EMBEDDED_OBJECT) { @@ -455,16 +485,18 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) { // Use signed delta-encoding for position. DCHECK(static_cast(rinfo->data()) == rinfo->data()); int pos_delta = static_cast(rinfo->data()) - last_position_; - int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag - : kStatementPositionTag; - // Check if delta is small enough to fit in a tagged byte. - if (is_intn(pos_delta, kSmallDataBits)) { - WriteTaggedPC(pc_delta, kLocatableTag); - WriteTaggedData(pos_delta, pos_type_tag); + if (rmode == RelocInfo::STATEMENT_POSITION) { + WritePosition(pc_delta, pos_delta, rmode); } else { - // Otherwise, use costly encoding. - WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag); - WriteExtraTaggedIntData(pos_delta, pos_type_tag); + DCHECK(rmode == RelocInfo::POSITION); + if (pc_delta != 0 || last_mode_ != RelocInfo::POSITION) { + FlushPosition(); + next_position_candidate_pc_delta_ = pc_delta; + next_position_candidate_pos_delta_ = pos_delta; + } else { + next_position_candidate_pos_delta_ += pos_delta; + } + next_position_candidate_flushed_ = false; } last_position_ = static_cast(rinfo->data()); } else if (RelocInfo::IsComment(rmode)) { @@ -486,6 +518,7 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) { WriteExtraTaggedPC(pc_delta, saved_mode); } last_pc_ = rinfo->pc(); + last_mode_ = rmode; #ifdef DEBUG DCHECK(begin_pos - pos_ <= kMaxSize); #endif diff --git a/src/assembler.h b/src/assembler.h index eff64ffd7e..8907b6a472 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -647,14 +647,24 @@ class RelocInfo { // lower addresses. class RelocInfoWriter BASE_EMBEDDED { public: - RelocInfoWriter() : pos_(NULL), - last_pc_(NULL), - last_id_(0), - last_position_(0) {} - RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), - last_pc_(pc), - last_id_(0), - last_position_(0) {} + RelocInfoWriter() + : pos_(NULL), + last_pc_(NULL), + last_id_(0), + last_position_(0), + last_mode_(RelocInfo::NUMBER_OF_MODES), + next_position_candidate_pos_delta_(0), + next_position_candidate_pc_delta_(0), + next_position_candidate_flushed_(true) {} + RelocInfoWriter(byte* pos, byte* pc) + : pos_(pos), + last_pc_(pc), + last_id_(0), + last_position_(0), + last_mode_(RelocInfo::NUMBER_OF_MODES), + next_position_candidate_pos_delta_(0), + next_position_candidate_pc_delta_(0), + next_position_candidate_flushed_(true) {} byte* pos() const { return pos_; } byte* last_pc() const { return last_pc_; } @@ -668,6 +678,8 @@ class RelocInfoWriter BASE_EMBEDDED { last_pc_ = pc; } + void Finish() { FlushPosition(); } + // Max size (bytes) of a written RelocInfo. Longest encoding is // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta. // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12. @@ -684,11 +696,19 @@ class RelocInfoWriter BASE_EMBEDDED { inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag); inline void WriteTaggedData(intptr_t data_delta, int tag); inline void WriteExtraTag(int extra_tag, int top_tag); + inline void WritePosition(int pc_delta, int pos_delta, RelocInfo::Mode rmode); + + void FlushPosition(); byte* pos_; byte* last_pc_; int last_id_; int last_position_; + RelocInfo::Mode last_mode_; + int next_position_candidate_pos_delta_; + uint32_t next_position_candidate_pc_delta_; + bool next_position_candidate_flushed_; + DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter); }; diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index 7e59ab9fa8..719dabc3f0 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -333,6 +333,7 @@ Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) void Assembler::GetCode(CodeDesc* desc) { // Finalize code (at this point overflow() may be true, but the gap ensures // that we are still not overlapping instructions and relocation info). + reloc_info_writer.Finish(); DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. // Set up code descriptor. desc->buffer = buffer_; diff --git a/src/ppc/assembler-ppc.cc b/src/ppc/assembler-ppc.cc index 4607ff9dc5..322f74a980 100644 --- a/src/ppc/assembler-ppc.cc +++ b/src/ppc/assembler-ppc.cc @@ -248,6 +248,7 @@ Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) void Assembler::GetCode(CodeDesc* desc) { + reloc_info_writer.Finish(); // Set up code descriptor. desc->buffer = buffer_; desc->buffer_size = buffer_size_; diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 3ce420e3e7..710a9c9b08 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -332,6 +332,7 @@ Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) void Assembler::GetCode(CodeDesc* desc) { // Finalize code (at this point overflow() may be true, but the gap ensures // that we are still not overlapping instructions and relocation info). + reloc_info_writer.Finish(); DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. // Set up code descriptor. desc->buffer = buffer_; diff --git a/src/x87/assembler-x87.cc b/src/x87/assembler-x87.cc index 0784592cc1..9176b57eba 100644 --- a/src/x87/assembler-x87.cc +++ b/src/x87/assembler-x87.cc @@ -256,6 +256,7 @@ Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) void Assembler::GetCode(CodeDesc* desc) { // Finalize code (at this point overflow() may be true, but the gap ensures // that we are still not overlapping instructions and relocation info). + reloc_info_writer.Finish(); DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. // Set up code descriptor. desc->buffer = buffer_; diff --git a/test/cctest/test-reloc-info.cc b/test/cctest/test-reloc-info.cc index 94ed287c44..a238c3a7d8 100644 --- a/test/cctest/test-reloc-info.cc +++ b/test/cctest/test-reloc-info.cc @@ -55,10 +55,16 @@ TEST(Positions) { for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) { RelocInfo::Mode mode = (i % 2 == 0) ? RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION; + if (mode == RelocInfo::STATEMENT_POSITION) { + printf("TEST WRITING STATEMENT %p %d\n", pc, pos); + } else { + printf("TEST WRITING POSITION %p %d\n", pc, pos); + } WriteRinfo(&writer, pc, mode, pos); CHECK(writer.pos() - RelocInfoWriter::kMaxSize >= relocation_info_end); } + writer.Finish(); relocation_info_size = static_cast(buffer_end - writer.pos()); CodeDesc desc = { buffer.get(), buffer_size, code_size, relocation_info_size, NULL }; @@ -68,6 +74,7 @@ TEST(Positions) { RelocIterator it(desc, RelocInfo::ModeMask(RelocInfo::POSITION)); pc = buffer.get(); for (int i = 0, pos = 0; i < 100; i++, pc += i, pos += i) { + printf("TESTING 1: %d\n", i); RelocInfo::Mode mode = (i % 2 == 0) ? RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION; if (mode == RelocInfo::POSITION) {