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