1c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
2c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// found in the LICENSE file.
4c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
5c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/source-position.h"
6c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/compilation-info.h"
7c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/objects-inl.h"
8c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
9c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace v8 {
10c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace internal {
11c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
12c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstd::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) {
13c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<SharedFunctionInfo> function(pos.function);
1462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  String* name = nullptr;
1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (function->script()->IsScript()) {
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Script* script = Script::cast(function->script());
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (script->name()->IsString()) {
1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      name = String::cast(script->name());
1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
21c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  out << "<";
2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (name != nullptr) {
2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    out << name->ToCString(DISALLOW_NULLS).get();
24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
25c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << "unknown";
26c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
27c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
28c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return out;
29c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
30c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
31c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstd::ostream& operator<<(std::ostream& out,
32c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                         const std::vector<SourcePositionInfo>& stack) {
33c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool first = true;
34c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  for (const SourcePositionInfo& pos : stack) {
35c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (!first) out << " inlined at ";
36c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << pos;
37c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    first = false;
38c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
39c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return out;
40c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
41c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
42c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstd::ostream& operator<<(std::ostream& out, const SourcePosition& pos) {
43c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (pos.isInlined()) {
44c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << "<inlined(" << pos.InliningId() << "):";
45c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
46c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << "<not inlined:";
47c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
48c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  out << pos.ScriptOffset() << ">";
49c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return out;
50c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
51c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
52c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstd::vector<SourcePositionInfo> SourcePosition::InliningStack(
53c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    CompilationInfo* cinfo) const {
54c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  SourcePosition pos = *this;
55c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  std::vector<SourcePositionInfo> stack;
56c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  while (pos.isInlined()) {
57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const auto& inl = cinfo->inlined_functions()[pos.InliningId()];
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    stack.push_back(SourcePositionInfo(pos, inl.shared_info));
59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    pos = inl.position.position;
60c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  stack.push_back(SourcePositionInfo(pos, cinfo->shared_info()));
62c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return stack;
63c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
64c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
65c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstd::vector<SourcePositionInfo> SourcePosition::InliningStack(
66c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Code> code) const {
67c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<DeoptimizationInputData> deopt_data(
68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      DeoptimizationInputData::cast(code->deoptimization_data()));
69c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  SourcePosition pos = *this;
70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  std::vector<SourcePositionInfo> stack;
71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  while (pos.isInlined()) {
72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InliningPosition inl =
73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        deopt_data->InliningPositions()->get(pos.InliningId());
74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<SharedFunctionInfo> function(
75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        deopt_data->GetInlinedFunction(inl.inlined_function_id));
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    stack.push_back(SourcePositionInfo(pos, function));
77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    pos = inl.position;
78c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
79c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<SharedFunctionInfo> function(
80c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  stack.push_back(SourcePositionInfo(pos, function));
82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return stack;
83c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
84c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
85c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid SourcePosition::Print(std::ostream& out,
86c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                           SharedFunctionInfo* function) const {
87c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Script::PositionInfo pos;
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Object* source_name = nullptr;
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (function->script()->IsScript()) {
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Script* script = Script::cast(function->script());
9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    source_name = script->name();
9262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    script->GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
94c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  out << "<";
9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (source_name != nullptr && source_name->IsString()) {
96c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << String::cast(source_name)
97c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch               ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
98c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch               .get();
99c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
100c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << "unknown";
101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
102c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
105c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid SourcePosition::Print(std::ostream& out, Code* code) const {
106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DeoptimizationInputData* deopt_data =
107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      DeoptimizationInputData::cast(code->deoptimization_data());
108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (!isInlined()) {
109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    SharedFunctionInfo* function(
110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()));
111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Print(out, function);
112c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    InliningPosition inl = deopt_data->InliningPositions()->get(InliningId());
114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (inl.inlined_function_id == -1) {
115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      out << *this;
116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    } else {
117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      SharedFunctionInfo* function =
118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          deopt_data->GetInlinedFunction(inl.inlined_function_id);
119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Print(out, function);
120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
121c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    out << " inlined at ";
122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    inl.position.Print(out, code);
123c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochSourcePositionInfo::SourcePositionInfo(SourcePosition pos,
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       Handle<SharedFunctionInfo> f)
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    : position(pos), function(f) {
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (function->script()->IsScript()) {
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Script> script(Script::cast(function->script()));
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Script::PositionInfo info;
13262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info,
13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                Script::WITH_OFFSET)) {
13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      line = info.line;
13562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      column = info.column;
13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
13762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
140c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}  // namespace internal
141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}  // namespace v8
142