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/codegen/source-position.h"
6 #include "src/codegen/optimized-compilation-info.h"
7 #include "src/objects/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 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
operator <<(std::ostream & out,const std::vector<SourcePositionInfo> & stack)23 std::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
operator <<(std::ostream & out,const SourcePosition & pos)34 std::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
InliningStack(OptimizedCompilationInfo * cinfo) const49 std::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
InliningStack(Handle<Code> code) const62 std::vector<SourcePositionInfo> SourcePosition::InliningStack(
63 Handle<Code> code) const {
64 Isolate* isolate = code->GetIsolate();
65 DeoptimizationData deopt_data =
66 DeoptimizationData::cast(code->deoptimization_data());
67 SourcePosition pos = *this;
68 std::vector<SourcePositionInfo> stack;
69 while (pos.isInlined()) {
70 InliningPosition inl = deopt_data.InliningPositions().get(pos.InliningId());
71 Handle<SharedFunctionInfo> function(
72 deopt_data.GetInlinedFunction(inl.inlined_function_id), isolate);
73 stack.push_back(SourcePositionInfo(pos, function));
74 pos = inl.position;
75 }
76 Handle<SharedFunctionInfo> function(
77 SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo()), isolate);
78 stack.push_back(SourcePositionInfo(pos, function));
79 return stack;
80 }
81
FirstInfo(Handle<Code> code) const82 SourcePositionInfo SourcePosition::FirstInfo(Handle<Code> code) const {
83 DisallowGarbageCollection no_gc;
84 Isolate* isolate = code->GetIsolate();
85 DeoptimizationData deopt_data =
86 DeoptimizationData::cast(code->deoptimization_data());
87 SourcePosition pos = *this;
88 if (pos.isInlined()) {
89 InliningPosition inl = deopt_data.InliningPositions().get(pos.InliningId());
90 Handle<SharedFunctionInfo> function(
91 deopt_data.GetInlinedFunction(inl.inlined_function_id), isolate);
92 return SourcePositionInfo(pos, function);
93 }
94 Handle<SharedFunctionInfo> function(
95 SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo()), isolate);
96 return SourcePositionInfo(pos, function);
97 }
98
Print(std::ostream & out,SharedFunctionInfo function) const99 void SourcePosition::Print(std::ostream& out,
100 SharedFunctionInfo function) const {
101 Script::PositionInfo pos;
102 Object source_name;
103 if (function.script().IsScript()) {
104 Script script = Script::cast(function.script());
105 source_name = script.name();
106 script.GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
107 }
108 out << "<";
109 if (source_name.IsString()) {
110 out << String::cast(source_name)
111 .ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
112 .get();
113 } else {
114 out << "unknown";
115 }
116 out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
117 }
118
PrintJson(std::ostream & out) const119 void SourcePosition::PrintJson(std::ostream& out) const {
120 if (IsExternal()) {
121 out << "{ \"line\" : " << ExternalLine() << ", "
122 << " \"fileId\" : " << ExternalFileId() << ", "
123 << " \"inliningId\" : " << InliningId() << "}";
124 } else {
125 out << "{ \"scriptOffset\" : " << ScriptOffset() << ", "
126 << " \"inliningId\" : " << InliningId() << "}";
127 }
128 }
129
Print(std::ostream & out,Code code) const130 void SourcePosition::Print(std::ostream& out, Code code) const {
131 DeoptimizationData deopt_data =
132 DeoptimizationData::cast(code.deoptimization_data());
133 if (!isInlined()) {
134 SharedFunctionInfo function(
135 SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo()));
136 Print(out, function);
137 } else {
138 InliningPosition inl = deopt_data.InliningPositions().get(InliningId());
139 if (inl.inlined_function_id == -1) {
140 out << *this;
141 } else {
142 SharedFunctionInfo function =
143 deopt_data.GetInlinedFunction(inl.inlined_function_id);
144 Print(out, function);
145 }
146 out << " inlined at ";
147 inl.position.Print(out, code);
148 }
149 }
150
SourcePositionInfo(SourcePosition pos,Handle<SharedFunctionInfo> f)151 SourcePositionInfo::SourcePositionInfo(SourcePosition pos,
152 Handle<SharedFunctionInfo> f)
153 : position(pos),
154 shared(f),
155 script(f.is_null() || !f->script().IsScript()
156 ? Handle<Script>::null()
157 : handle(Script::cast(f->script()), f->GetIsolate())) {
158 if (!script.is_null()) {
159 Script::PositionInfo info;
160 if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info,
161 Script::WITH_OFFSET)) {
162 line = info.line;
163 column = info.column;
164 }
165 }
166 }
167
168 } // namespace internal
169 } // namespace v8
170