Line data Source code
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 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 : class Code;
19 : class OptimizedCompilationInfo;
20 : class Script;
21 : class SharedFunctionInfo;
22 : struct SourcePositionInfo;
23 :
24 : // SourcePosition stores
25 : // - is_external (1 bit true/false)
26 : //
27 : // - if is_external is true:
28 : // - external_line (20 bits, non-negative int)
29 : // - external_file_id (10 bits, non-negative int)
30 : //
31 : // - if is_external is false:
32 : // - script_offset (30 bit non-negative int or kNoSourcePosition)
33 : //
34 : // - In both cases, there is an inlining_id.
35 : // - inlining_id (16 bit non-negative int or kNotInlined).
36 : //
37 : // An "external" SourcePosition is one given by a file_id and a line,
38 : // suitable for embedding references to .cc or .tq files.
39 : // Otherwise, a SourcePosition contains an offset into a JavaScript
40 : // file.
41 : //
42 : // A defined inlining_id refers to positions in
43 : // OptimizedCompilationInfo::inlined_functions or
44 : // DeoptimizationData::InliningPositions, depending on the compilation stage.
45 : class SourcePosition final {
46 : public:
47 : explicit SourcePosition(int script_offset, int inlining_id = kNotInlined)
48 3159374 : : value_(0) {
49 : SetIsExternal(false);
50 : SetScriptOffset(script_offset);
51 : SetInliningId(inlining_id);
52 : }
53 :
54 : // External SourcePositions should use the following method to construct
55 : // SourcePositions to avoid confusion.
56 : static SourcePosition External(int line, int file_id) {
57 : return SourcePosition(line, file_id, kNotInlined);
58 : }
59 :
60 : static SourcePosition Unknown() { return SourcePosition(kNoSourcePosition); }
61 : bool IsKnown() const {
62 156144416 : if (IsExternal()) return true;
63 187096843 : return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined;
64 : }
65 : bool isInlined() const {
66 1681 : if (IsExternal()) return false;
67 1681 : return InliningId() != kNotInlined;
68 : }
69 :
70 39685484 : bool IsExternal() const { return IsExternalField::decode(value_); }
71 : bool IsJavaScript() const { return !IsExternal(); }
72 :
73 : int ExternalLine() const {
74 : DCHECK(IsExternal());
75 : return ExternalLineField::decode(value_);
76 : }
77 :
78 : int ExternalFileId() const {
79 : DCHECK(IsExternal());
80 : return ExternalFileIdField::decode(value_);
81 : }
82 :
83 : // Assumes that the code object is optimized
84 : std::vector<SourcePositionInfo> InliningStack(Handle<Code> code) const;
85 : std::vector<SourcePositionInfo> InliningStack(
86 : OptimizedCompilationInfo* cinfo) const;
87 :
88 : void Print(std::ostream& out, Code code) const;
89 : void PrintJson(std::ostream& out) const;
90 :
91 : int ScriptOffset() const {
92 : DCHECK(IsJavaScript());
93 104080231 : return ScriptOffsetField::decode(value_) - 1;
94 : }
95 9739710 : int InliningId() const { return InliningIdField::decode(value_) - 1; }
96 :
97 : void SetIsExternal(bool external) {
98 : value_ = IsExternalField::update(value_, external);
99 : }
100 : void SetExternalLine(int line) {
101 : DCHECK(IsExternal());
102 : DCHECK(line <= ExternalLineField::kMax - 1);
103 : value_ = ExternalLineField::update(value_, line);
104 : }
105 : void SetExternalFileId(int file_id) {
106 : DCHECK(IsExternal());
107 : DCHECK(file_id <= ExternalFileIdField::kMax - 1);
108 : value_ = ExternalFileIdField::update(value_, file_id);
109 : }
110 :
111 : void SetScriptOffset(int script_offset) {
112 : DCHECK(IsJavaScript());
113 : DCHECK(script_offset <= ScriptOffsetField::kMax - 2);
114 : DCHECK_GE(script_offset, kNoSourcePosition);
115 39283877 : value_ = ScriptOffsetField::update(value_, script_offset + 1);
116 : }
117 : void SetInliningId(int inlining_id) {
118 : DCHECK(inlining_id <= InliningIdField::kMax - 2);
119 : DCHECK_GE(inlining_id, kNotInlined);
120 36644234 : value_ = InliningIdField::update(value_, inlining_id + 1);
121 : }
122 :
123 : static const int kNotInlined = -1;
124 : STATIC_ASSERT(kNoSourcePosition == -1);
125 :
126 143182360 : int64_t raw() const { return static_cast<int64_t>(value_); }
127 : static SourcePosition FromRaw(int64_t raw) {
128 : SourcePosition position = Unknown();
129 : DCHECK_GE(raw, 0);
130 229972896 : position.value_ = static_cast<uint64_t>(raw);
131 : return position;
132 : }
133 :
134 : private:
135 : // Used by SourcePosition::External(line, file_id).
136 : SourcePosition(int line, int file_id, int inlining_id) : value_(0) {
137 : SetIsExternal(true);
138 : SetExternalLine(line);
139 : SetExternalFileId(file_id);
140 : SetInliningId(inlining_id);
141 : }
142 :
143 : void Print(std::ostream& out, SharedFunctionInfo function) const;
144 :
145 : typedef BitField64<bool, 0, 1> IsExternalField;
146 :
147 : // The two below are only used if IsExternal() is true.
148 : typedef BitField64<int, 1, 20> ExternalLineField;
149 : typedef BitField64<int, 21, 10> ExternalFileIdField;
150 :
151 : // ScriptOffsetField is only used if IsExternal() is false.
152 : typedef BitField64<int, 1, 30> ScriptOffsetField;
153 :
154 : // InliningId is in the high bits for better compression in
155 : // SourcePositionTable.
156 : typedef BitField64<int, 31, 16> InliningIdField;
157 :
158 : // Leaving the highest bit untouched to allow for signed conversion.
159 : uint64_t value_;
160 : };
161 :
162 : inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) {
163 : return lhs.raw() == rhs.raw();
164 : }
165 :
166 : inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) {
167 : return !(lhs == rhs);
168 : }
169 :
170 65818 : struct InliningPosition {
171 : // position of the inlined call
172 : SourcePosition position = SourcePosition::Unknown();
173 :
174 : // references position in DeoptimizationData::literals()
175 : int inlined_function_id;
176 : };
177 :
178 : struct SourcePositionInfo {
179 : SourcePositionInfo(SourcePosition pos, Handle<SharedFunctionInfo> f);
180 :
181 : SourcePosition position;
182 : Handle<SharedFunctionInfo> shared;
183 : Handle<Script> script;
184 : int line = -1;
185 : int column = -1;
186 : };
187 :
188 : std::ostream& operator<<(std::ostream& out, const SourcePosition& pos);
189 :
190 : std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos);
191 : std::ostream& operator<<(std::ostream& out,
192 : const std::vector<SourcePositionInfo>& stack);
193 :
194 : } // namespace internal
195 : } // namespace v8
196 :
197 : #endif // V8_SOURCE_POSITION_H_
|