| // Copyright 2016 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_SOURCE_POSITION_H_ |
| #define V8_SOURCE_POSITION_H_ |
| |
| #include <ostream> |
| |
| #include "src/flags.h" |
| #include "src/globals.h" |
| #include "src/handles.h" |
| #include "src/utils.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class Code; |
| class CompilationInfo; |
| class Script; |
| class SharedFunctionInfo; |
| struct SourcePositionInfo; |
| |
| // SourcePosition stores |
| // - script_offset (31 bit non-negative int or kNoSourcePosition) |
| // - inlining_id (16 bit non-negative int or kNotInlined). |
| // |
| // A defined inlining_id refers to positions in |
| // CompilationInfo::inlined_functions or |
| // DeoptimizationData::InliningPositions, depending on the compilation stage. |
| class SourcePosition final { |
| public: |
| explicit SourcePosition(int script_offset, int inlining_id = kNotInlined) |
| : value_(0) { |
| SetScriptOffset(script_offset); |
| SetInliningId(inlining_id); |
| } |
| |
| static SourcePosition Unknown() { return SourcePosition(kNoSourcePosition); } |
| bool IsKnown() const { |
| return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined; |
| } |
| bool isInlined() const { return InliningId() != kNotInlined; } |
| |
| // Assumes that the code object is optimized |
| std::vector<SourcePositionInfo> InliningStack(Handle<Code> code) const; |
| std::vector<SourcePositionInfo> InliningStack(CompilationInfo* cinfo) const; |
| |
| void Print(std::ostream& out, Code* code) const; |
| |
| int ScriptOffset() const { return ScriptOffsetField::decode(value_) - 1; } |
| int InliningId() const { return InliningIdField::decode(value_) - 1; } |
| |
| void SetScriptOffset(int script_offset) { |
| DCHECK(script_offset <= ScriptOffsetField::kMax - 2); |
| DCHECK_GE(script_offset, kNoSourcePosition); |
| value_ = ScriptOffsetField::update(value_, script_offset + 1); |
| } |
| void SetInliningId(int inlining_id) { |
| DCHECK(inlining_id <= InliningIdField::kMax - 2); |
| DCHECK_GE(inlining_id, kNotInlined); |
| value_ = InliningIdField::update(value_, inlining_id + 1); |
| } |
| |
| static const int kNotInlined = -1; |
| STATIC_ASSERT(kNoSourcePosition == -1); |
| |
| int64_t raw() const { return static_cast<int64_t>(value_); } |
| static SourcePosition FromRaw(int64_t raw) { |
| SourcePosition position = Unknown(); |
| DCHECK_GE(raw, 0); |
| position.value_ = static_cast<uint64_t>(raw); |
| return position; |
| } |
| |
| private: |
| void Print(std::ostream& out, SharedFunctionInfo* function) const; |
| |
| // InliningId is in the high bits for better compression in |
| // SourcePositionTable. |
| typedef BitField64<int, 0, 31> ScriptOffsetField; |
| typedef BitField64<int, 31, 16> InliningIdField; |
| // Leaving the highest bit untouched to allow for signed conversion. |
| uint64_t value_; |
| }; |
| |
| inline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) { |
| return lhs.raw() == rhs.raw(); |
| } |
| |
| inline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) { |
| return !(lhs == rhs); |
| } |
| |
| struct InliningPosition { |
| // position of the inlined call |
| SourcePosition position = SourcePosition::Unknown(); |
| |
| // references position in DeoptimizationData::literals() |
| int inlined_function_id; |
| }; |
| |
| struct SourcePositionInfo { |
| SourcePositionInfo(SourcePosition pos, Handle<SharedFunctionInfo> f); |
| |
| SourcePosition position; |
| Handle<SharedFunctionInfo> function; |
| int line = -1; |
| int column = -1; |
| }; |
| |
| std::ostream& operator<<(std::ostream& out, const SourcePosition& pos); |
| |
| std::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos); |
| std::ostream& operator<<(std::ostream& out, |
| const std::vector<SourcePositionInfo>& stack); |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_SOURCE_POSITION_H_ |