df071e9497
Now, the CodeAssembler can annotate Nodes with SourcePositions. SourcePositions themselves get a new mode "external," in which they get a file_id, line and column. The file_id is currently maintained in the isolate, mapping to strings for filenames. Additionally, inlining information is ignored at this point, but in the long run I'd like to recognize calls to different CSA functions as manual inlinings. At this point, if you want to see the results in tools like GDB, you'll need to build without clang, and use the GCC toolchain. GN flag is_clang=false will do the trick. Bug: v8:8418 Change-Id: I123cdc041612285fa7d0ba532a625bceeda5d338 Reviewed-on: https://chromium-review.googlesource.com/c/1322954 Commit-Queue: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#59009}
154 lines
4.8 KiB
C++
154 lines
4.8 KiB
C++
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "src/source-position.h"
|
|
#include "src/objects-inl.h"
|
|
#include "src/optimized-compilation-info.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) {
|
|
out << "<";
|
|
if (!pos.script.is_null() && pos.script->name()->IsString()) {
|
|
out << String::cast(pos.script->name())->ToCString(DISALLOW_NULLS).get();
|
|
} else {
|
|
out << "unknown";
|
|
}
|
|
out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
|
|
return out;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& out,
|
|
const std::vector<SourcePositionInfo>& stack) {
|
|
bool first = true;
|
|
for (const SourcePositionInfo& pos : stack) {
|
|
if (!first) out << " inlined at ";
|
|
out << pos;
|
|
first = false;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) {
|
|
if (pos.isInlined()) {
|
|
out << "<inlined(" << pos.InliningId() << "):";
|
|
} else {
|
|
out << "<not inlined:";
|
|
}
|
|
|
|
if (pos.IsExternal()) {
|
|
out << pos.ExternalLine() << ", " << pos.ExternalFileId() << ">";
|
|
} else {
|
|
out << pos.ScriptOffset() << ">";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::vector<SourcePositionInfo> SourcePosition::InliningStack(
|
|
OptimizedCompilationInfo* cinfo) const {
|
|
SourcePosition pos = *this;
|
|
std::vector<SourcePositionInfo> stack;
|
|
while (pos.isInlined()) {
|
|
const auto& inl = cinfo->inlined_functions()[pos.InliningId()];
|
|
stack.push_back(SourcePositionInfo(pos, inl.shared_info));
|
|
pos = inl.position.position;
|
|
}
|
|
stack.push_back(SourcePositionInfo(pos, cinfo->shared_info()));
|
|
return stack;
|
|
}
|
|
|
|
std::vector<SourcePositionInfo> SourcePosition::InliningStack(
|
|
Handle<Code> code) const {
|
|
Isolate* isolate = code->GetIsolate();
|
|
Handle<DeoptimizationData> deopt_data(
|
|
DeoptimizationData::cast(code->deoptimization_data()), isolate);
|
|
SourcePosition pos = *this;
|
|
std::vector<SourcePositionInfo> stack;
|
|
while (pos.isInlined()) {
|
|
InliningPosition inl =
|
|
deopt_data->InliningPositions()->get(pos.InliningId());
|
|
Handle<SharedFunctionInfo> function(
|
|
deopt_data->GetInlinedFunction(inl.inlined_function_id), isolate);
|
|
stack.push_back(SourcePositionInfo(pos, function));
|
|
pos = inl.position;
|
|
}
|
|
Handle<SharedFunctionInfo> function(
|
|
SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()), isolate);
|
|
stack.push_back(SourcePositionInfo(pos, function));
|
|
return stack;
|
|
}
|
|
|
|
void SourcePosition::Print(std::ostream& out,
|
|
SharedFunctionInfo function) const {
|
|
Script::PositionInfo pos;
|
|
Object source_name;
|
|
if (function->script()->IsScript()) {
|
|
Script script = Script::cast(function->script());
|
|
source_name = script->name();
|
|
script->GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
|
|
}
|
|
out << "<";
|
|
if (source_name->IsString()) {
|
|
out << String::cast(source_name)
|
|
->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
|
|
.get();
|
|
} else {
|
|
out << "unknown";
|
|
}
|
|
out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
|
|
}
|
|
|
|
void SourcePosition::PrintJson(std::ostream& out) const {
|
|
if (IsExternal()) {
|
|
out << "{ \"line\" : " << ExternalLine() << ", "
|
|
<< " \"fileId\" : " << ExternalFileId() << ", "
|
|
<< " \"inliningId\" : " << InliningId() << "}";
|
|
} else {
|
|
out << "{ \"scriptOffset\" : " << ScriptOffset() << ", "
|
|
<< " \"inliningId\" : " << InliningId() << "}";
|
|
}
|
|
}
|
|
|
|
void SourcePosition::Print(std::ostream& out, Code code) const {
|
|
DeoptimizationData deopt_data =
|
|
DeoptimizationData::cast(code->deoptimization_data());
|
|
if (!isInlined()) {
|
|
SharedFunctionInfo function(
|
|
SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
|
|
Print(out, function);
|
|
} else {
|
|
InliningPosition inl = deopt_data->InliningPositions()->get(InliningId());
|
|
if (inl.inlined_function_id == -1) {
|
|
out << *this;
|
|
} else {
|
|
SharedFunctionInfo function =
|
|
deopt_data->GetInlinedFunction(inl.inlined_function_id);
|
|
Print(out, function);
|
|
}
|
|
out << " inlined at ";
|
|
inl.position.Print(out, code);
|
|
}
|
|
}
|
|
|
|
SourcePositionInfo::SourcePositionInfo(SourcePosition pos,
|
|
Handle<SharedFunctionInfo> f)
|
|
: position(pos),
|
|
shared(f),
|
|
script(f.is_null() || !f->script()->IsScript()
|
|
? Handle<Script>::null()
|
|
: handle(Script::cast(f->script()), f->GetIsolate())) {
|
|
if (!script.is_null()) {
|
|
Script::PositionInfo info;
|
|
if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info,
|
|
Script::WITH_OFFSET)) {
|
|
line = info.line;
|
|
column = info.column;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|