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/compilation-info.h"
7 #include "src/objects-inl.h"
8
9 namespace v8 {
10 namespace internal {
11
operator <<(std::ostream & out,const SourcePositionInfo & pos)12 std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) {
13 Handle<SharedFunctionInfo> function(pos.function);
14 Handle<Script> script(Script::cast(function->script()));
15 out << "<";
16 if (script->name()->IsString()) {
17 out << String::cast(script->name())->ToCString(DISALLOW_NULLS).get();
18 } else {
19 out << "unknown";
20 }
21 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
22 return out;
23 }
24
operator <<(std::ostream & out,const std::vector<SourcePositionInfo> & stack)25 std::ostream& operator<<(std::ostream& out,
26 const std::vector<SourcePositionInfo>& stack) {
27 bool first = true;
28 for (const SourcePositionInfo& pos : stack) {
29 if (!first) out << " inlined at ";
30 out << pos;
31 first = false;
32 }
33 return out;
34 }
35
operator <<(std::ostream & out,const SourcePosition & pos)36 std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) {
37 if (pos.isInlined()) {
38 out << "<inlined(" << pos.InliningId() << "):";
39 } else {
40 out << "<not inlined:";
41 }
42 out << pos.ScriptOffset() << ">";
43 return out;
44 }
45
Info(Handle<SharedFunctionInfo> function) const46 SourcePositionInfo SourcePosition::Info(
47 Handle<SharedFunctionInfo> function) const {
48 SourcePositionInfo result(*this, function);
49 Handle<Script> script(Script::cast(function->script()));
50 Script::PositionInfo pos;
51 if (Script::GetPositionInfo(script, ScriptOffset(), &pos,
52 Script::WITH_OFFSET)) {
53 result.line = pos.line;
54 result.column = pos.column;
55 }
56 return result;
57 }
58
InliningStack(CompilationInfo * cinfo) const59 std::vector<SourcePositionInfo> SourcePosition::InliningStack(
60 CompilationInfo* cinfo) const {
61 SourcePosition pos = *this;
62 std::vector<SourcePositionInfo> stack;
63 while (pos.isInlined()) {
64 const auto& inl = cinfo->inlined_functions()[pos.InliningId()];
65 stack.push_back(pos.Info(inl.shared_info));
66 pos = inl.position.position;
67 }
68 stack.push_back(pos.Info(cinfo->shared_info()));
69 return stack;
70 }
71
InliningStack(Handle<Code> code) const72 std::vector<SourcePositionInfo> SourcePosition::InliningStack(
73 Handle<Code> code) const {
74 Handle<DeoptimizationInputData> deopt_data(
75 DeoptimizationInputData::cast(code->deoptimization_data()));
76 SourcePosition pos = *this;
77 std::vector<SourcePositionInfo> stack;
78 while (pos.isInlined()) {
79 InliningPosition inl =
80 deopt_data->InliningPositions()->get(pos.InliningId());
81 Handle<SharedFunctionInfo> function(
82 deopt_data->GetInlinedFunction(inl.inlined_function_id));
83 stack.push_back(pos.Info(function));
84 pos = inl.position;
85 }
86 Handle<SharedFunctionInfo> function(
87 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
88 stack.push_back(pos.Info(function));
89 return stack;
90 }
91
Print(std::ostream & out,SharedFunctionInfo * function) const92 void SourcePosition::Print(std::ostream& out,
93 SharedFunctionInfo* function) const {
94 Script* script = Script::cast(function->script());
95 Object* source_name = script->name();
96 Script::PositionInfo pos;
97 script->GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
98 out << "<";
99 if (source_name->IsString()) {
100 out << String::cast(source_name)
101 ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
102 .get();
103 } else {
104 out << "unknown";
105 }
106 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
107 }
108
Print(std::ostream & out,Code * code) const109 void SourcePosition::Print(std::ostream& out, Code* code) const {
110 DeoptimizationInputData* deopt_data =
111 DeoptimizationInputData::cast(code->deoptimization_data());
112 if (!isInlined()) {
113 SharedFunctionInfo* function(
114 SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
115 Print(out, function);
116 } else {
117 InliningPosition inl = deopt_data->InliningPositions()->get(InliningId());
118 if (inl.inlined_function_id == -1) {
119 out << *this;
120 } else {
121 SharedFunctionInfo* function =
122 deopt_data->GetInlinedFunction(inl.inlined_function_id);
123 Print(out, function);
124 }
125 out << " inlined at ";
126 inl.position.Print(out, code);
127 }
128 }
129
130 } // namespace internal
131 } // namespace v8
132