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 15namespace v8 { 16namespace internal { 17 18class Code; 19class OptimizedCompilationInfo; 20class Script; 21class SharedFunctionInfo; 22struct 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. 45class 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. 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 if (IsExternal()) return true; 63 return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined; 64 } 65 bool isInlined() const { 66 if (IsExternal()) return false; 67 return InliningId() != kNotInlined; 68 } 69 70 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 SourcePositionInfo FirstInfo(Handle<Code> code) const; 88 89 void Print(std::ostream& out, Code code) const; 90 void PrintJson(std::ostream& out) const; 91 92 int ScriptOffset() const { 93 DCHECK(IsJavaScript()); 94 return ScriptOffsetField::decode(value_) - 1; 95 } 96 int InliningId() const { return InliningIdField::decode(value_) - 1; } 97 98 void SetIsExternal(bool external) { 99 value_ = IsExternalField::update(value_, external); 100 } 101 void SetExternalLine(int line) { 102 DCHECK(IsExternal()); 103 DCHECK(line <= ExternalLineField::kMax - 1); 104 value_ = ExternalLineField::update(value_, line); 105 } 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 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 } 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 127 int64_t raw() const { return static_cast<int64_t>(value_); } 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). 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 163inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) { 164 return lhs.raw() == rhs.raw(); 165} 166 167inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) { 168 return !(lhs == rhs); 169} 170 171struct 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 179struct 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 189std::ostream& operator<<(std::ostream& out, const SourcePosition& pos); 190 191std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos); 192std::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