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