source-position.cc 4.81 KB
Newer Older
1 2 3 4
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#include "src/codegen/source-position.h"
#include "src/codegen/optimized-compilation-info.h"
7
#include "src/objects/objects-inl.h"
8 9 10 11 12

namespace v8 {
namespace internal {

std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos) {
13
  out << "<";
14 15
  if (!pos.script.is_null() && pos.script->name().IsString()) {
    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 21 22 23 24
  return out;
}

std::ostream& operator<<(std::ostream& out,
                         const std::vector<SourcePositionInfo>& stack) {
25 26 27 28 29
  bool first = true;
  for (const SourcePositionInfo& pos : stack) {
    if (!first) out << " inlined at ";
    out << pos;
    first = false;
30 31 32 33 34 35 36 37 38 39
  }
  return out;
}

std::ostream& operator<<(std::ostream& out, const SourcePosition& pos) {
  if (pos.isInlined()) {
    out << "<inlined(" << pos.InliningId() << "):";
  } else {
    out << "<not inlined:";
  }
40 41 42 43 44 45

  if (pos.IsExternal()) {
    out << pos.ExternalLine() << ", " << pos.ExternalFileId() << ">";
  } else {
    out << pos.ScriptOffset() << ">";
  }
46 47 48 49
  return out;
}

std::vector<SourcePositionInfo> SourcePosition::InliningStack(
50
    OptimizedCompilationInfo* cinfo) const {
51 52 53 54
  SourcePosition pos = *this;
  std::vector<SourcePositionInfo> stack;
  while (pos.isInlined()) {
    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 62 63
}

std::vector<SourcePositionInfo> SourcePosition::InliningStack(
    Handle<Code> code) const {
64
  Isolate* isolate = code->GetIsolate();
65
  Handle<DeoptimizationData> deopt_data(
66
      DeoptimizationData::cast(code->deoptimization_data()), isolate);
67 68 69 70
  SourcePosition pos = *this;
  std::vector<SourcePositionInfo> stack;
  while (pos.isInlined()) {
    InliningPosition inl =
71
        deopt_data->InliningPositions().get(pos.InliningId());
72
    Handle<SharedFunctionInfo> function(
73
        deopt_data->GetInlinedFunction(inl.inlined_function_id), isolate);
74
    stack.push_back(SourcePositionInfo(pos, function));
75
    pos = inl.position;
76
  }
77
  Handle<SharedFunctionInfo> function(
78
      SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo()), isolate);
79
  stack.push_back(SourcePositionInfo(pos, function));
80
  return stack;
81 82 83
}

void SourcePosition::Print(std::ostream& out,
84
                           SharedFunctionInfo function) const {
85
  Script::PositionInfo pos;
86
  Object source_name;
87 88 89 90
  if (function.script().IsScript()) {
    Script script = Script::cast(function.script());
    source_name = script.name();
    script.GetPositionInfo(ScriptOffset(), &pos, Script::WITH_OFFSET);
91
  }
92
  out << "<";
93
  if (source_name.IsString()) {
94
    out << String::cast(source_name)
95
               .ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
96 97 98 99 100 101 102
               .get();
  } else {
    out << "unknown";
  }
  out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
}

103
void SourcePosition::PrintJson(std::ostream& out) const {
104 105 106 107 108 109 110 111
  if (IsExternal()) {
    out << "{ \"line\" : " << ExternalLine() << ", "
        << "  \"fileId\" : " << ExternalFileId() << ", "
        << "  \"inliningId\" : " << InliningId() << "}";
  } else {
    out << "{ \"scriptOffset\" : " << ScriptOffset() << ", "
        << "  \"inliningId\" : " << InliningId() << "}";
  }
112 113
}

114
void SourcePosition::Print(std::ostream& out, Code code) const {
115
  DeoptimizationData deopt_data =
116
      DeoptimizationData::cast(code.deoptimization_data());
117
  if (!isInlined()) {
118
    SharedFunctionInfo function(
119
        SharedFunctionInfo::cast(deopt_data.SharedFunctionInfo()));
120 121
    Print(out, function);
  } else {
122
    InliningPosition inl = deopt_data.InliningPositions().get(InliningId());
123 124 125
    if (inl.inlined_function_id == -1) {
      out << *this;
    } else {
126
      SharedFunctionInfo function =
127
          deopt_data.GetInlinedFunction(inl.inlined_function_id);
128 129 130 131 132 133 134
      Print(out, function);
    }
    out << " inlined at ";
    inl.position.Print(out, code);
  }
}

135 136
SourcePositionInfo::SourcePositionInfo(SourcePosition pos,
                                       Handle<SharedFunctionInfo> f)
137
    : position(pos),
138
      shared(f),
139
      script(f.is_null() || !f->script().IsScript()
140
                 ? Handle<Script>::null()
141
                 : handle(Script::cast(f->script()), f->GetIsolate())) {
142
  if (!script.is_null()) {
143 144 145 146 147 148
    Script::PositionInfo info;
    if (Script::GetPositionInfo(script, pos.ScriptOffset(), &info,
                                Script::WITH_OFFSET)) {
      line = info.line;
      column = info.column;
    }
149 150 151
  }
}

152 153
}  // namespace internal
}  // namespace v8