1// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/source-position.h"
6#include "src/objects-inl.h"
7#include "src/optimized-compilation-info.h"
8
9namespace v8 {
10namespace internal {
11
12std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) {
13 out << "<";
14 if (!pos.script.is_null() && pos.script->name()->IsString()) {
15 out << String::cast(pos.script->name())->ToCString(DISALLOW_NULLS).get();
16 } else {
17 out << "unknown";
18 }
19 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
20 return out;
21}
22
23std::ostream& operator<<(std::ostream& out,
24 const std::vector<SourcePositionInfo>& stack) {
25 bool first = true;
26 for (const SourcePositionInfo& pos : stack) {
27 if (!first) out << " inlined at ";
28 out << pos;
29 first = false;
30 }
31 return out;
32}
33
34std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) {
35 if (pos.isInlined()) {
36 out << "<inlined(" << pos.InliningId() << "):";
37 } else {
38 out << "<not inlined:";
39 }
40
41 if (pos.IsExternal()) {
42 out << pos.ExternalLine() << ", " << pos.ExternalFileId() << ">";
43 } else {
44 out << pos.ScriptOffset() << ">";
45 }
46 return out;
47}
48
49std::vector<SourcePositionInfo> SourcePosition::InliningStack(
50 OptimizedCompilationInfo* cinfo) const {
51 SourcePosition pos = *this;
52 std::vector<SourcePositionInfo> stack;
53 while (pos.isInlined()) {
54 const auto& inl = cinfo->inlined_functions()[pos.InliningId()];
55 stack.push_back(SourcePositionInfo(pos, inl.shared_info));
56 pos = inl.position.position;
57 }
58 stack.push_back(SourcePositionInfo(pos, cinfo->shared_info()));
59 return stack;
60}
61
62std::vector<SourcePositionInfo> SourcePosition::InliningStack(
63 Handle<Code> code) const {
64 Isolate* isolate = code->GetIsolate();
65 Handle<DeoptimizationData> deopt_data(
66 DeoptimizationData::cast(code->deoptimization_data()), isolate);
67 SourcePosition pos = *this;
68 std::vector<SourcePositionInfo> stack;
69 while (pos.isInlined()) {
70 InliningPosition inl =
71 deopt_data->InliningPositions()->get(pos.InliningId());
72 Handle<SharedFunctionInfo> function(
73 deopt_data->GetInlinedFunction(inl.inlined_function_id), isolate);
74 stack.push_back(SourcePositionInfo(pos, function));
75 pos = inl.position;
76 }
77 Handle<SharedFunctionInfo> function(
78 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()), isolate);
79 stack.push_back(SourcePositionInfo(pos, function));
80 return stack;
81}
82
83void SourcePosition::Print(std::ostream& out,
84 SharedFunctionInfo function) const {
85 Script::PositionInfo pos;
86 Object source_name;
87 if (function->script()->IsScript()) {
88 Script script = Script::cast(function->script());
89 source_name = script->name();
90 script->GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
91 }
92 out << "<";
93 if (source_name->IsString()) {
94 out << String::cast(source_name)
95 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
96 .get();
97 } else {
98 out << "unknown";
99 }
100 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
101}
102
103void SourcePosition::PrintJson(std::ostream& out) const {
104 if (IsExternal()) {
105 out << "{ \"line\" : " << ExternalLine() << ", "
106 << " \"fileId\" : " << ExternalFileId() << ", "
107 << " \"inliningId\" : " << InliningId() << "}";
108 } else {
109 out << "{ \"scriptOffset\" : " << ScriptOffset() << ", "
110 << " \"inliningId\" : " << InliningId() << "}";
111 }
112}
113
114void SourcePosition::Print(std::ostream& out, Code code) const {
115 DeoptimizationData deopt_data =
116 DeoptimizationData::cast(code->deoptimization_data());
117 if (!isInlined()) {
118 SharedFunctionInfo function(
119 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
120 Print(out, function);
121 } else {
122 InliningPosition inl = deopt_data->InliningPositions()->get(InliningId());
123 if (inl.inlined_function_id == -1) {
124 out << *this;
125 } else {
126 SharedFunctionInfo function =
127 deopt_data->GetInlinedFunction(inl.inlined_function_id);
128 Print(out, function);
129 }
130 out << " inlined at ";
131 inl.position.Print(out, code);
132 }
133}
134
135SourcePositionInfo::SourcePositionInfo(SourcePosition pos,
136 Handle<SharedFunctionInfo> f)
137 : position(pos),
138 shared(f),
139 script(f.is_null() || !f->script()->IsScript()
140 ? Handle<Script>::null()
141 : handle(Script::cast(f->script()), f->GetIsolate())) {
142 if (!script.is_null()) {
143 Script::PositionInfo info;
144 if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info,
145 Script::WITH_OFFSET)) {
146 line = info.line;
147 column = info.column;
148 }
149 }
150}
151
152} // namespace internal
153} // namespace v8
154