• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CODEGEN_SOURCE_POSITION_H_
6 #define V8_CODEGEN_SOURCE_POSITION_H_
7 
8 #include <iosfwd>
9 
10 #include "src/base/bit-field.h"
11 #include "src/common/globals.h"
12 #include "src/flags/flags.h"
13 #include "src/handles/handles.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       : 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.
External(int line,int file_id)56   static SourcePosition External(int line, int file_id) {
57     return SourcePosition(line, file_id, kNotInlined);
58   }
59 
Unknown()60   static SourcePosition Unknown() { return SourcePosition(kNoSourcePosition); }
IsKnown()61   bool IsKnown() const {
62     if (IsExternal()) return true;
63     return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined;
64   }
isInlined()65   bool isInlined() const {
66     if (IsExternal()) return false;
67     return InliningId() != kNotInlined;
68   }
69 
IsExternal()70   bool IsExternal() const { return IsExternalField::decode(value_); }
IsJavaScript()71   bool IsJavaScript() const { return !IsExternal(); }
72 
ExternalLine()73   int ExternalLine() const {
74     DCHECK(IsExternal());
75     return ExternalLineField::decode(value_);
76   }
77 
ExternalFileId()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   SourcePositionInfo FirstInfo(Handle<Code> code) const;
88 
89   void Print(std::ostream& out, Code code) const;
90   void PrintJson(std::ostream& out) const;
91 
ScriptOffset()92   int ScriptOffset() const {
93     DCHECK(IsJavaScript());
94     return ScriptOffsetField::decode(value_) - 1;
95   }
InliningId()96   int InliningId() const { return InliningIdField::decode(value_) - 1; }
97 
SetIsExternal(bool external)98   void SetIsExternal(bool external) {
99     value_ = IsExternalField::update(value_, external);
100   }
SetExternalLine(int line)101   void SetExternalLine(int line) {
102     DCHECK(IsExternal());
103     DCHECK(line <= ExternalLineField::kMax - 1);
104     value_ = ExternalLineField::update(value_, line);
105   }
SetExternalFileId(int file_id)106   void SetExternalFileId(int file_id) {
107     DCHECK(IsExternal());
108     DCHECK(file_id <= ExternalFileIdField::kMax - 1);
109     value_ = ExternalFileIdField::update(value_, file_id);
110   }
111 
SetScriptOffset(int script_offset)112   void SetScriptOffset(int script_offset) {
113     DCHECK(IsJavaScript());
114     DCHECK(script_offset <= ScriptOffsetField::kMax - 2);
115     DCHECK_GE(script_offset, kNoSourcePosition);
116     value_ = ScriptOffsetField::update(value_, script_offset + 1);
117   }
SetInliningId(int inlining_id)118   void SetInliningId(int inlining_id) {
119     DCHECK(inlining_id <= InliningIdField::kMax - 2);
120     DCHECK_GE(inlining_id, kNotInlined);
121     value_ = InliningIdField::update(value_, inlining_id + 1);
122   }
123 
124   static const int kNotInlined = -1;
125   STATIC_ASSERT(kNoSourcePosition == -1);
126 
raw()127   int64_t raw() const { return static_cast<int64_t>(value_); }
FromRaw(int64_t raw)128   static SourcePosition FromRaw(int64_t raw) {
129     SourcePosition position = Unknown();
130     DCHECK_GE(raw, 0);
131     position.value_ = static_cast<uint64_t>(raw);
132     return position;
133   }
134 
135  private:
136   // Used by SourcePosition::External(line, file_id).
SourcePosition(int line,int file_id,int inlining_id)137   SourcePosition(int line, int file_id, int inlining_id) : value_(0) {
138     SetIsExternal(true);
139     SetExternalLine(line);
140     SetExternalFileId(file_id);
141     SetInliningId(inlining_id);
142   }
143 
144   void Print(std::ostream& out, SharedFunctionInfo function) const;
145 
146   using IsExternalField = base::BitField64<bool, 0, 1>;
147 
148   // The two below are only used if IsExternal() is true.
149   using ExternalLineField = base::BitField64<int, 1, 20>;
150   using ExternalFileIdField = base::BitField64<int, 21, 10>;
151 
152   // ScriptOffsetField is only used if IsExternal() is false.
153   using ScriptOffsetField = base::BitField64<int, 1, 30>;
154 
155   // InliningId is in the high bits for better compression in
156   // SourcePositionTable.
157   using InliningIdField = base::BitField64<int, 31, 16>;
158 
159   // Leaving the highest bit untouched to allow for signed conversion.
160   uint64_t value_;
161 };
162 
163 inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) {
164   return lhs.raw() == rhs.raw();
165 }
166 
167 inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) {
168   return !(lhs == rhs);
169 }
170 
171 struct InliningPosition {
172   // position of the inlined call
173   SourcePosition position = SourcePosition::Unknown();
174 
175   // references position in DeoptimizationData::literals()
176   int inlined_function_id;
177 };
178 
179 struct SourcePositionInfo {
180   SourcePositionInfo(SourcePosition pos, Handle<SharedFunctionInfo> f);
181 
182   SourcePosition position;
183   Handle<SharedFunctionInfo> shared;
184   Handle<Script> script;
185   int line = -1;
186   int column = -1;
187 };
188 
189 std::ostream& operator<<(std::ostream& out, const SourcePosition& pos);
190 
191 std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos);
192 std::ostream& operator<<(std::ostream& out,
193                          const std::vector<SourcePositionInfo>& stack);
194 
195 }  // namespace internal
196 }  // namespace v8
197 
198 #endif  // V8_CODEGEN_SOURCE_POSITION_H_
199