Commit 44748584 authored by yangguo's avatar yangguo Committed by Commit bot

Use source position table in turbofan code.

R=bmeurer@chromium.org
BUG=v8:5117

Review-Url: https://codereview.chromium.org/2109673003
Cr-Commit-Position: refs/heads/master@{#37392}
parent aa1628ab
......@@ -52,7 +52,8 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
last_lazy_deopt_pc_(0),
jump_tables_(nullptr),
ools_(nullptr),
osr_pc_offset_(-1) {
osr_pc_offset_(-1),
source_position_table_builder_(info->isolate(), zone()) {
for (int i = 0; i < code->InstructionBlockCount(); ++i) {
new (&labels_[i]) Label;
}
......@@ -73,8 +74,8 @@ Handle<Code> CodeGenerator::GenerateCode() {
FrameScope frame_scope(masm(), StackFrame::MANUAL);
// Emit a code line info recording start event.
PositionsRecorder* recorder = masm()->positions_recorder();
LOG_CODE_EVENT(isolate(), CodeStartLinePosInfoRecordEvent(recorder));
LOG_CODE_EVENT(isolate(), CodeStartLinePosInfoRecordEvent(
&source_position_table_builder_));
// Place function entry hook if requested to do so.
if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
......@@ -209,6 +210,9 @@ Handle<Code> CodeGenerator::GenerateCode() {
result->set_is_turbofanned(true);
result->set_stack_slots(frame()->GetTotalFrameSlotCount());
result->set_safepoint_table_offset(safepoints()->GetCodeOffset());
Handle<ByteArray> source_positions =
source_position_table_builder_.ToSourcePositionTable();
result->set_source_position_table(*source_positions);
// Emit exception handler table.
if (!handlers_.empty()) {
......@@ -235,7 +239,7 @@ Handle<Code> CodeGenerator::GenerateCode() {
}
// Emit a code line info recording stop event.
void* line_info = recorder->DetachJITHandlerData();
void* line_info = source_position_table_builder_.DetachJITHandlerData();
LOG_CODE_EVENT(isolate(), CodeEndLinePosInfoRecordEvent(
AbstractCode::cast(*result), line_info));
......@@ -398,7 +402,8 @@ void CodeGenerator::AssembleSourcePosition(Instruction* instr) {
current_source_position_ = source_position;
if (source_position.IsUnknown()) return;
int code_pos = source_position.raw();
masm()->positions_recorder()->RecordPosition(code_pos);
source_position_table_builder_.AddPosition(masm()->pc_offset(), code_pos,
false);
if (FLAG_code_comments) {
CompilationInfo* info = this->info();
if (!info->parse_info()) return;
......
......@@ -10,6 +10,7 @@
#include "src/deoptimizer.h"
#include "src/macro-assembler.h"
#include "src/safepoint-table.h"
#include "src/source-position-table.h"
namespace v8 {
namespace internal {
......@@ -241,6 +242,7 @@ class CodeGenerator final : public GapResolver::Assembler {
JumpTable* jump_tables_;
OutOfLineCode* ools_;
int osr_pc_offset_;
SourcePositionTableBuilder source_position_table_builder_;
};
} // namespace compiler
......
......@@ -79,17 +79,18 @@ Handle<Object> FrameInspector::GetExpression(int index) {
int FrameInspector::GetSourcePosition() {
if (is_optimized_) {
return deoptimized_frame_->GetSourcePosition();
} else if (is_interpreted_) {
if (is_optimized_) return deoptimized_frame_->GetSourcePosition();
AbstractCode* code;
int code_offset;
if (is_interpreted_) {
InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
BytecodeArray* bytecode_array = frame->GetBytecodeArray();
return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
code = AbstractCode::cast(frame->GetBytecodeArray());
code_offset = frame->GetBytecodeOffset();
} else {
Code* code = frame_->LookupCode();
int offset = static_cast<int>(frame_->pc() - code->instruction_start());
return code->SourcePosition(offset);
code = AbstractCode::cast(frame_->LookupCode());
code_offset = static_cast<int>(frame_->pc() - code->instruction_start());
}
return code->SourcePosition(code_offset);
}
......
......@@ -2775,19 +2775,20 @@ Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
// static
int Deoptimizer::ComputeSourcePosition(SharedFunctionInfo* shared,
BailoutId node_id) {
if (shared->HasBytecodeArray()) {
BytecodeArray* bytecodes = shared->bytecode_array();
AbstractCode* abstract_code = shared->abstract_code();
int code_offset;
if (abstract_code->IsBytecodeArray()) {
// BailoutId points to the next bytecode in the bytecode aray. Subtract
// 1 to get the end of current bytecode.
return bytecodes->SourcePosition(node_id.ToInt() - 1);
code_offset = node_id.ToInt() - 1;
} else {
Code* non_optimized_code = shared->code();
FixedArray* raw_data = non_optimized_code->deoptimization_data();
FixedArray* raw_data = abstract_code->GetCode()->deoptimization_data();
DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, shared);
unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
return non_optimized_code->SourcePosition(pc_offset);
code_offset =
static_cast<int>(FullCodeGenerator::PcField::decode(pc_and_state));
}
return abstract_code->SourcePosition(code_offset);
}
// static
......
......@@ -951,7 +951,7 @@ void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code,
PrintF(file, "+%d", code_offset);
if (print_line_number) {
SharedFunctionInfo* shared = function->shared();
int source_pos = code->SourcePosition(code_offset);
int source_pos = AbstractCode::cast(code)->SourcePosition(code_offset);
Object* maybe_script = shared->script();
if (maybe_script->IsScript()) {
Script* script = Script::cast(maybe_script);
......@@ -1480,7 +1480,7 @@ void JavaScriptFrame::Print(StringStream* accumulator,
if (code != NULL && code->kind() == Code::FUNCTION &&
pc >= code->instruction_start() && pc < code->instruction_end()) {
int offset = static_cast<int>(pc - code->instruction_start());
int source_pos = code->SourcePosition(offset);
int source_pos = AbstractCode::cast(code)->SourcePosition(offset);
int line = script->GetLineNumber(source_pos) + 1;
accumulator->Add(":%d] [pc=%p]", line, pc);
} else if (is_interpreted()) {
......@@ -1488,7 +1488,7 @@ void JavaScriptFrame::Print(StringStream* accumulator,
reinterpret_cast<const InterpretedFrame*>(this);
BytecodeArray* bytecodes = iframe->GetBytecodeArray();
int offset = iframe->GetBytecodeOffset();
int source_pos = bytecodes->SourcePosition(offset);
int source_pos = AbstractCode::cast(bytecodes)->SourcePosition(offset);
int line = script->GetLineNumber(source_pos) + 1;
accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset);
} else {
......
......@@ -35,6 +35,7 @@ void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
for (int i = 0; i < deopt_data->DeoptCount(); i++) {
int pc_offset = deopt_data->Pc(i)->value();
if (pc_offset == -1) continue;
pc_offset = pc_offset + 1; // We will encode the pc offset after the call.
DCHECK_GE(pc_offset, prev_pc_offset);
int pc_delta = pc_offset - prev_pc_offset;
// We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
......
......@@ -652,7 +652,7 @@ class CaptureStackTraceHelper {
if (!column_key_.is_null()) {
Code* code = frame->LookupCode();
int offset = static_cast<int>(frame->pc() - code->instruction_start());
int position = code->SourcePosition(offset);
int position = AbstractCode::cast(code)->SourcePosition(offset);
// Make position 1-based.
if (position >= 0) ++position;
JSObject::AddProperty(stack_frame, column_key_,
......@@ -1354,20 +1354,19 @@ void Isolate::PrintCurrentStackTrace(FILE* out) {
HandleScope scope(this);
// Find code position if recorded in relocation info.
StandardFrame* frame = it.frame();
int pos;
AbstractCode* abstract_code;
int code_offset;
if (frame->is_interpreted()) {
InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
pos = iframe->GetBytecodeArray()->SourcePosition(
iframe->GetBytecodeOffset());
} else if (frame->is_java_script()) {
Code* code = frame->LookupCode();
int offset = static_cast<int>(frame->pc() - code->instruction_start());
pos = frame->LookupCode()->SourcePosition(offset);
abstract_code = AbstractCode::cast(iframe->GetBytecodeArray());
code_offset = iframe->GetBytecodeOffset();
} else {
DCHECK(frame->is_wasm());
// TODO(clemensh): include wasm frames here
continue;
DCHECK(frame->is_java_script() || frame->is_wasm());
Code* code = frame->LookupCode();
abstract_code = AbstractCode::cast(code);
code_offset = static_cast<int>(frame->pc() - code->instruction_start());
}
int pos = abstract_code->SourcePosition(code_offset);
JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
Handle<Object> pos_obj(Smi::FromInt(pos), this);
// Fetch function and receiver.
......
......@@ -5280,6 +5280,14 @@ int AbstractCode::instruction_size() {
}
}
ByteArray* AbstractCode::source_position_table() {
if (IsCode()) {
return GetCode()->source_position_table();
} else {
return GetBytecodeArray()->source_position_table();
}
}
int AbstractCode::SizeIncludingMetadata() {
if (IsCode()) {
return GetCode()->SizeIncludingMetadata();
......
......@@ -13583,65 +13583,6 @@ void Code::CopyFrom(const CodeDesc& desc) {
Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
}
// Locate the source position which is closest to the code offset. This is
// using the source position information embedded in the relocation info.
// The position returned is relative to the beginning of the script where the
// source for this function is found.
int Code::SourcePosition(int code_offset) {
int position = RelocInfo::kNoPosition; // Initially no position found.
// Subtract one because the current PC is one instruction after the call site.
code_offset--;
// Find the closest position attached to a pc lower or equal to the current.
// Note that the pc of reloc infos grow monotonically.
if (kind() == FUNCTION || (is_optimized_code() && !is_turbofanned())) {
for (SourcePositionTableIterator it(source_position_table());
!it.done() && it.code_offset() <= code_offset; it.Advance()) {
position = it.source_position();
}
} else {
Address pc = instruction_start() + code_offset;
for (RelocIterator it(this, RelocInfo::kPositionMask);
!it.done() && it.rinfo()->pc() <= pc; it.next()) {
position = static_cast<int>(it.rinfo()->data());
}
}
DCHECK(kind() == FUNCTION || (is_optimized_code() && is_turbofanned()) ||
is_wasm_code() || position == RelocInfo::kNoPosition);
return position;
}
// Same as Code::SourcePosition above except it only looks for statement
// positions.
int Code::SourceStatementPosition(int code_offset) {
// First find the closest position.
int position = SourcePosition(code_offset);
// Now find the closest statement position before the position.
int statement_position = 0;
if (kind() == FUNCTION || (is_optimized_code() && !is_turbofanned())) {
for (SourcePositionTableIterator it(source_position_table()); !it.done();
it.Advance()) {
if (it.is_statement()) {
int p = it.source_position();
if (statement_position < p && p <= position) {
statement_position = p;
}
}
}
} else {
for (RelocIterator it(this, RelocInfo::kPositionMask); !it.done();
it.next()) {
if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
int p = static_cast<int>(it.rinfo()->data());
if (statement_position < p && p <= position) {
statement_position = p;
}
}
}
}
return statement_position;
}
SafepointEntry Code::GetSafepointEntry(Address pc) {
SafepointTable table(this);
......@@ -13716,13 +13657,32 @@ void Code::ClearInlineCaches() {
}
int AbstractCode::SourcePosition(int offset) {
return IsBytecodeArray() ? GetBytecodeArray()->SourcePosition(offset)
: GetCode()->SourcePosition(offset);
int position = 0;
// Subtract one because the current PC is one instruction after the call site.
if (IsCode()) offset--;
for (SourcePositionTableIterator iterator(source_position_table());
!iterator.done() && iterator.code_offset() <= offset;
iterator.Advance()) {
position = iterator.source_position();
}
return position;
}
int AbstractCode::SourceStatementPosition(int offset) {
return IsBytecodeArray() ? GetBytecodeArray()->SourceStatementPosition(offset)
: GetCode()->SourceStatementPosition(offset);
// First find the closest position.
int position = SourcePosition(offset);
// Now find the closest statement position before the position.
int statement_position = 0;
for (SourcePositionTableIterator it(source_position_table()); !it.done();
it.Advance()) {
if (it.is_statement()) {
int p = it.source_position();
if (statement_position < p && p <= position) {
statement_position = p;
}
}
}
return statement_position;
}
void JSFunction::ClearTypeFeedbackInfo() {
......@@ -14438,32 +14398,6 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
}
#endif // ENABLE_DISASSEMBLER
int BytecodeArray::SourcePosition(int offset) {
int last_position = 0;
for (SourcePositionTableIterator iterator(source_position_table());
!iterator.done() && iterator.code_offset() <= offset;
iterator.Advance()) {
last_position = iterator.source_position();
}
return last_position;
}
int BytecodeArray::SourceStatementPosition(int offset) {
// First find the closest position.
int position = SourcePosition(offset);
// Now find the closest statement position before the position.
int statement_position = 0;
for (SourcePositionTableIterator it(source_position_table()); !it.done();
it.Advance()) {
if (it.is_statement()) {
int p = it.source_position();
if (statement_position < p && p <= position) {
statement_position = p;
}
}
}
return statement_position;
}
void BytecodeArray::Disassemble(std::ostream& os) {
os << "Parameter count " << parameter_count() << "\n";
......@@ -18970,19 +18904,23 @@ void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
int JSGeneratorObject::source_position() const {
CHECK(is_suspended());
AbstractCode* code;
int code_offset;
if (function()->shared()->HasBytecodeArray()) {
// New-style generators.
int offset = Smi::cast(input_or_debug_pos())->value();
code_offset = Smi::cast(input_or_debug_pos())->value();
// The stored bytecode offset is relative to a different base than what
// is used in the source position table, hence the subtraction.
offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
return function()->shared()->bytecode_array()->SourcePosition(offset);
code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
code = AbstractCode::cast(function()->shared()->bytecode_array());
} else {
// Old-style generators.
int offset = continuation();
CHECK(0 <= offset && offset < function()->code()->instruction_size());
return function()->code()->SourcePosition(offset);
code_offset = continuation();
CHECK(0 <= code_offset);
CHECK(code_offset < function()->code()->instruction_size());
code = AbstractCode::cast(function()->shared()->code());
}
return code->SourcePosition(code_offset);
}
// static
......
......@@ -5267,10 +5267,6 @@ class Code: public HeapObject {
// the layout of the code object into account.
inline int ExecutableSize();
// Locating source position.
int SourcePosition(int code_offset);
int SourceStatementPosition(int code_offset);
DECLARE_CAST(Code)
// Dispatched behavior.
......@@ -5497,6 +5493,9 @@ class AbstractCode : public HeapObject {
// Returns the size of the code instructions.
inline int instruction_size();
// Return the source position table.
inline ByteArray* source_position_table();
// Returns the size of instructions and the metadata.
inline int SizeIncludingMetadata();
......
......@@ -88,51 +88,23 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
JITLineInfoTable* line_table = NULL;
if (script) {
line_table = new JITLineInfoTable();
if (abstract_code->IsCode()) {
Code* code = abstract_code->GetCode();
int start_position = shared->start_position();
int end_position = shared->end_position();
if (code->kind() == Code::FUNCTION ||
(code->is_optimized_code() && !code->is_turbofanned())) {
for (SourcePositionTableIterator it(code->source_position_table());
!it.done(); it.Advance()) {
int position = it.source_position();
// TODO(alph): in case of inlining the position may correspond to an
// inlined function source code. Do not collect positions that fall
// beyond the function source code. There's however a chance the
// inlined function has similar positions but in another script. So
// the proper fix is to store script_id in some form along with the
// inlined function positions.
if (position < start_position || position >= end_position) continue;
int line_number = script->GetLineNumber(it.source_position()) + 1;
int pc_offset = it.code_offset() + Code::kHeaderSize;
line_table->SetPosition(pc_offset, line_number);
}
} else {
for (RelocIterator it(code); !it.done(); it.next()) {
RelocInfo* reloc_info = it.rinfo();
if (!RelocInfo::IsPosition(reloc_info->rmode())) continue;
int position = static_cast<int>(reloc_info->data());
// TODO(alph): in case of inlining the position may correspond to an
// inlined function source code. Do not collect positions that fall
// beyond the function source code. There's however a chance the
// inlined function has similar positions but in another script. So
// the proper fix is to store script_id in some form along with the
// inlined function positions.
if (position < start_position || position >= end_position) continue;
int pc_offset = static_cast<int>(reloc_info->pc() - code->address());
int line_number = script->GetLineNumber(position) + 1;
line_table->SetPosition(pc_offset, line_number);
}
}
} else {
BytecodeArray* bytecode = abstract_code->GetBytecodeArray();
SourcePositionTableIterator it(bytecode->source_position_table());
for (; !it.done(); it.Advance()) {
int line_number = script->GetLineNumber(it.source_position()) + 1;
int pc_offset = it.code_offset() + BytecodeArray::kHeaderSize;
line_table->SetPosition(pc_offset, line_number);
}
int offset = abstract_code->IsCode() ? Code::kHeaderSize
: BytecodeArray::kHeaderSize;
int start_position = shared->start_position();
int end_position = shared->end_position();
for (SourcePositionTableIterator it(abstract_code->source_position_table());
!it.done(); it.Advance()) {
int position = it.source_position();
// TODO(alph): in case of inlining the position may correspond to an
// inlined function source code. Do not collect positions that fall
// beyond the function source code. There's however a chance the
// inlined function has similar positions but in another script. So
// the proper fix is to store script_id in some form along with the
// inlined function positions.
if (position < start_position || position >= end_position) continue;
int line_number = script->GetLineNumber(position) + 1;
int pc_offset = it.code_offset() + offset;
line_table->SetPosition(pc_offset, line_number);
}
}
rec->entry = NewCodeEntry(
......
......@@ -35,6 +35,7 @@ void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
for (int i = 0; i < deopt_data->DeoptCount(); i++) {
int pc_offset = deopt_data->Pc(i)->value();
if (pc_offset == -1) continue;
pc_offset = pc_offset + 1; // We will encode the pc offset after the call.
DCHECK_GE(pc_offset, prev_pc_offset);
int pc_delta = pc_offset - prev_pc_offset;
// We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment