// 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 OptimizedCompilationInfo; 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 // OptimizedCompilationInfo::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( OptimizedCompilationInfo* cinfo) const; void Print(std::ostream& out, Code code) const; void PrintJson(std::ostream& out) 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<Script> script; 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_