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#ifndef V8_SOURCE_POSITION_H_
6#define V8_SOURCE_POSITION_H_
7
8#include <ostream>
9
10#include "src/flags.h"
11#include "src/globals.h"
12#include "src/handles.h"
13#include "src/utils.h"
14
15namespace v8 {
16namespace internal {
17
18class Code;
19class CompilationInfo;
20class Script;
21class SharedFunctionInfo;
22struct SourcePositionInfo;
23
24// SourcePosition stores
25// - script_offset (31 bit non-negative int or kNoSourcePosition)
26// - inlining_id (16 bit non-negative int or kNotInlined).
27//
28// A defined inlining_id refers to positions in
29// CompilationInfo::inlined_functions or
30// DeoptimizationInputData::InliningPositions, depending on the compilation
31// stage.
32class SourcePosition final {
33 public:
34  explicit SourcePosition(int script_offset, int inlining_id = kNotInlined)
35      : value_(0) {
36    SetScriptOffset(script_offset);
37    SetInliningId(inlining_id);
38  }
39
40  static SourcePosition Unknown() { return SourcePosition(kNoSourcePosition); }
41  bool IsKnown() const {
42    return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined;
43  }
44  bool isInlined() const { return InliningId() != kNotInlined; }
45
46  // Assumes that the code object is optimized
47  std::vector<SourcePositionInfo> InliningStack(Handle<Code> code) const;
48  std::vector<SourcePositionInfo> InliningStack(CompilationInfo* cinfo) const;
49
50  void Print(std::ostream& out, Code* code) const;
51
52  int ScriptOffset() const { return ScriptOffsetField::decode(value_) - 1; }
53  int InliningId() const { return InliningIdField::decode(value_) - 1; }
54
55  void SetScriptOffset(int script_offset) {
56    DCHECK(script_offset <= ScriptOffsetField::kMax - 2);
57    DCHECK(script_offset >= kNoSourcePosition);
58    value_ = ScriptOffsetField::update(value_, script_offset + 1);
59  }
60  void SetInliningId(int inlining_id) {
61    DCHECK(inlining_id <= InliningIdField::kMax - 2);
62    DCHECK(inlining_id >= kNotInlined);
63    value_ = InliningIdField::update(value_, inlining_id + 1);
64  }
65
66  static const int kNotInlined = -1;
67  STATIC_ASSERT(kNoSourcePosition == -1);
68
69  int64_t raw() const { return static_cast<int64_t>(value_); }
70  static SourcePosition FromRaw(int64_t raw) {
71    SourcePosition position = Unknown();
72    DCHECK_GE(raw, 0);
73    position.value_ = static_cast<uint64_t>(raw);
74    return position;
75  }
76
77 private:
78  void Print(std::ostream& out, SharedFunctionInfo* function) const;
79
80  // InliningId is in the high bits for better compression in
81  // SourcePositionTable.
82  typedef BitField64<int, 0, 31> ScriptOffsetField;
83  typedef BitField64<int, 31, 16> InliningIdField;
84  // Leaving the highest bit untouched to allow for signed conversion.
85  uint64_t value_;
86};
87
88inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) {
89  return lhs.raw() == rhs.raw();
90}
91
92inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) {
93  return !(lhs == rhs);
94}
95
96struct InliningPosition {
97  // position of the inlined call
98  SourcePosition position = SourcePosition::Unknown();
99
100  // references position in DeoptimizationInputData::literals()
101  int inlined_function_id;
102};
103
104struct SourcePositionInfo {
105  SourcePositionInfo(SourcePosition pos, Handle<SharedFunctionInfo> f);
106
107  SourcePosition position;
108  Handle<SharedFunctionInfo> function;
109  int line = -1;
110  int column = -1;
111};
112
113std::ostream& operator<<(std::ostream& out, const SourcePosition& pos);
114
115std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos);
116std::ostream& operator<<(std::ostream& out,
117                         const std::vector<SourcePositionInfo>& stack);
118
119}  // namespace internal
120}  // namespace v8
121
122#endif  // V8_SOURCE_POSITION_H_
123