Remove redundant source position information in RelocInfo

Previously, emitting two more more unique source positions at the same pc would
generate two or more RelocInfo entries. Now, only the last emitted source
position for any pc is added to the RelocInfo.

Review URL: https://codereview.chromium.org/908443002

Cr-Commit-Position: refs/heads/master@{#26608}
This commit is contained in:
danno 2015-02-12 04:15:14 -08:00 committed by Commit bot
parent 295ab27830
commit e87c0bac35
9 changed files with 84 additions and 18 deletions

View File

@ -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);

View File

@ -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());

View File

@ -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<uint32_t>(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<int>(rinfo->data()) == rinfo->data());
int pos_delta = static_cast<int>(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<int>(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

View File

@ -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);
};

View File

@ -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_;

View File

@ -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_;

View File

@ -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_;

View File

@ -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_;

View File

@ -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<int>(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) {