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