11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_SOURCE_POSITION_H_
61cb0ef41Sopenharmony_ci#define V8_CODEGEN_SOURCE_POSITION_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <iosfwd>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/base/bit-field.h"
111cb0ef41Sopenharmony_ci#include "src/common/globals.h"
121cb0ef41Sopenharmony_ci#include "src/flags/flags.h"
131cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cinamespace v8 {
161cb0ef41Sopenharmony_cinamespace internal {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciclass Code;
191cb0ef41Sopenharmony_ciclass OptimizedCompilationInfo;
201cb0ef41Sopenharmony_ciclass Script;
211cb0ef41Sopenharmony_ciclass SharedFunctionInfo;
221cb0ef41Sopenharmony_cistruct SourcePositionInfo;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// SourcePosition stores
251cb0ef41Sopenharmony_ci// - is_external (1 bit true/false)
261cb0ef41Sopenharmony_ci//
271cb0ef41Sopenharmony_ci// - if is_external is true:
281cb0ef41Sopenharmony_ci// - external_line (20 bits, non-negative int)
291cb0ef41Sopenharmony_ci// - external_file_id (10 bits, non-negative int)
301cb0ef41Sopenharmony_ci//
311cb0ef41Sopenharmony_ci// - if is_external is false:
321cb0ef41Sopenharmony_ci// - script_offset (30 bit non-negative int or kNoSourcePosition)
331cb0ef41Sopenharmony_ci//
341cb0ef41Sopenharmony_ci// - In both cases, there is an inlining_id.
351cb0ef41Sopenharmony_ci// - inlining_id (16 bit non-negative int or kNotInlined).
361cb0ef41Sopenharmony_ci//
371cb0ef41Sopenharmony_ci// An "external" SourcePosition is one given by a file_id and a line,
381cb0ef41Sopenharmony_ci// suitable for embedding references to .cc or .tq files.
391cb0ef41Sopenharmony_ci// Otherwise, a SourcePosition contains an offset into a JavaScript
401cb0ef41Sopenharmony_ci// file.
411cb0ef41Sopenharmony_ci//
421cb0ef41Sopenharmony_ci// A defined inlining_id refers to positions in
431cb0ef41Sopenharmony_ci// OptimizedCompilationInfo::inlined_functions or
441cb0ef41Sopenharmony_ci// DeoptimizationData::InliningPositions, depending on the compilation stage.
451cb0ef41Sopenharmony_ciclass SourcePosition final {
461cb0ef41Sopenharmony_ci public:
471cb0ef41Sopenharmony_ci  explicit SourcePosition(int script_offset, int inlining_id = kNotInlined)
481cb0ef41Sopenharmony_ci      : value_(0) {
491cb0ef41Sopenharmony_ci    SetIsExternal(false);
501cb0ef41Sopenharmony_ci    SetScriptOffset(script_offset);
511cb0ef41Sopenharmony_ci    SetInliningId(inlining_id);
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // External SourcePositions should use the following method to construct
551cb0ef41Sopenharmony_ci  // SourcePositions to avoid confusion.
561cb0ef41Sopenharmony_ci  static SourcePosition External(int line, int file_id) {
571cb0ef41Sopenharmony_ci    return SourcePosition(line, file_id, kNotInlined);
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  static SourcePosition Unknown() { return SourcePosition(kNoSourcePosition); }
611cb0ef41Sopenharmony_ci  bool IsKnown() const {
621cb0ef41Sopenharmony_ci    if (IsExternal()) return true;
631cb0ef41Sopenharmony_ci    return ScriptOffset() != kNoSourcePosition || InliningId() != kNotInlined;
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci  bool isInlined() const {
661cb0ef41Sopenharmony_ci    if (IsExternal()) return false;
671cb0ef41Sopenharmony_ci    return InliningId() != kNotInlined;
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  bool IsExternal() const { return IsExternalField::decode(value_); }
711cb0ef41Sopenharmony_ci  bool IsJavaScript() const { return !IsExternal(); }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  int ExternalLine() const {
741cb0ef41Sopenharmony_ci    DCHECK(IsExternal());
751cb0ef41Sopenharmony_ci    return ExternalLineField::decode(value_);
761cb0ef41Sopenharmony_ci  }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  int ExternalFileId() const {
791cb0ef41Sopenharmony_ci    DCHECK(IsExternal());
801cb0ef41Sopenharmony_ci    return ExternalFileIdField::decode(value_);
811cb0ef41Sopenharmony_ci  }
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  // Assumes that the code object is optimized
841cb0ef41Sopenharmony_ci  std::vector<SourcePositionInfo> InliningStack(Handle<Code> code) const;
851cb0ef41Sopenharmony_ci  std::vector<SourcePositionInfo> InliningStack(
861cb0ef41Sopenharmony_ci      OptimizedCompilationInfo* cinfo) const;
871cb0ef41Sopenharmony_ci  SourcePositionInfo FirstInfo(Handle<Code> code) const;
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  void Print(std::ostream& out, Code code) const;
901cb0ef41Sopenharmony_ci  void PrintJson(std::ostream& out) const;
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  int ScriptOffset() const {
931cb0ef41Sopenharmony_ci    DCHECK(IsJavaScript());
941cb0ef41Sopenharmony_ci    return ScriptOffsetField::decode(value_) - 1;
951cb0ef41Sopenharmony_ci  }
961cb0ef41Sopenharmony_ci  int InliningId() const { return InliningIdField::decode(value_) - 1; }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  void SetIsExternal(bool external) {
991cb0ef41Sopenharmony_ci    value_ = IsExternalField::update(value_, external);
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci  void SetExternalLine(int line) {
1021cb0ef41Sopenharmony_ci    DCHECK(IsExternal());
1031cb0ef41Sopenharmony_ci    DCHECK(line <= ExternalLineField::kMax - 1);
1041cb0ef41Sopenharmony_ci    value_ = ExternalLineField::update(value_, line);
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci  void SetExternalFileId(int file_id) {
1071cb0ef41Sopenharmony_ci    DCHECK(IsExternal());
1081cb0ef41Sopenharmony_ci    DCHECK(file_id <= ExternalFileIdField::kMax - 1);
1091cb0ef41Sopenharmony_ci    value_ = ExternalFileIdField::update(value_, file_id);
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  void SetScriptOffset(int script_offset) {
1131cb0ef41Sopenharmony_ci    DCHECK(IsJavaScript());
1141cb0ef41Sopenharmony_ci    DCHECK(script_offset <= ScriptOffsetField::kMax - 2);
1151cb0ef41Sopenharmony_ci    DCHECK_GE(script_offset, kNoSourcePosition);
1161cb0ef41Sopenharmony_ci    value_ = ScriptOffsetField::update(value_, script_offset + 1);
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci  void SetInliningId(int inlining_id) {
1191cb0ef41Sopenharmony_ci    DCHECK(inlining_id <= InliningIdField::kMax - 2);
1201cb0ef41Sopenharmony_ci    DCHECK_GE(inlining_id, kNotInlined);
1211cb0ef41Sopenharmony_ci    value_ = InliningIdField::update(value_, inlining_id + 1);
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  static const int kNotInlined = -1;
1251cb0ef41Sopenharmony_ci  STATIC_ASSERT(kNoSourcePosition == -1);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  int64_t raw() const { return static_cast<int64_t>(value_); }
1281cb0ef41Sopenharmony_ci  static SourcePosition FromRaw(int64_t raw) {
1291cb0ef41Sopenharmony_ci    SourcePosition position = Unknown();
1301cb0ef41Sopenharmony_ci    DCHECK_GE(raw, 0);
1311cb0ef41Sopenharmony_ci    position.value_ = static_cast<uint64_t>(raw);
1321cb0ef41Sopenharmony_ci    return position;
1331cb0ef41Sopenharmony_ci  }
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci private:
1361cb0ef41Sopenharmony_ci  // Used by SourcePosition::External(line, file_id).
1371cb0ef41Sopenharmony_ci  SourcePosition(int line, int file_id, int inlining_id) : value_(0) {
1381cb0ef41Sopenharmony_ci    SetIsExternal(true);
1391cb0ef41Sopenharmony_ci    SetExternalLine(line);
1401cb0ef41Sopenharmony_ci    SetExternalFileId(file_id);
1411cb0ef41Sopenharmony_ci    SetInliningId(inlining_id);
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  void Print(std::ostream& out, SharedFunctionInfo function) const;
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  using IsExternalField = base::BitField64<bool, 0, 1>;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  // The two below are only used if IsExternal() is true.
1491cb0ef41Sopenharmony_ci  using ExternalLineField = base::BitField64<int, 1, 20>;
1501cb0ef41Sopenharmony_ci  using ExternalFileIdField = base::BitField64<int, 21, 10>;
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  // ScriptOffsetField is only used if IsExternal() is false.
1531cb0ef41Sopenharmony_ci  using ScriptOffsetField = base::BitField64<int, 1, 30>;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  // InliningId is in the high bits for better compression in
1561cb0ef41Sopenharmony_ci  // SourcePositionTable.
1571cb0ef41Sopenharmony_ci  using InliningIdField = base::BitField64<int, 31, 16>;
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  // Leaving the highest bit untouched to allow for signed conversion.
1601cb0ef41Sopenharmony_ci  uint64_t value_;
1611cb0ef41Sopenharmony_ci};
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ciinline bool operator==(const SourcePosition& lhs, const SourcePosition& rhs) {
1641cb0ef41Sopenharmony_ci  return lhs.raw() == rhs.raw();
1651cb0ef41Sopenharmony_ci}
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ciinline bool operator!=(const SourcePosition& lhs, const SourcePosition& rhs) {
1681cb0ef41Sopenharmony_ci  return !(lhs == rhs);
1691cb0ef41Sopenharmony_ci}
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_cistruct InliningPosition {
1721cb0ef41Sopenharmony_ci  // position of the inlined call
1731cb0ef41Sopenharmony_ci  SourcePosition position = SourcePosition::Unknown();
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // references position in DeoptimizationData::literals()
1761cb0ef41Sopenharmony_ci  int inlined_function_id;
1771cb0ef41Sopenharmony_ci};
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_cistruct SourcePositionInfo {
1801cb0ef41Sopenharmony_ci  SourcePositionInfo(SourcePosition pos, Handle<SharedFunctionInfo> f);
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  SourcePosition position;
1831cb0ef41Sopenharmony_ci  Handle<SharedFunctionInfo> shared;
1841cb0ef41Sopenharmony_ci  Handle<Script> script;
1851cb0ef41Sopenharmony_ci  int line = -1;
1861cb0ef41Sopenharmony_ci  int column = -1;
1871cb0ef41Sopenharmony_ci};
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& out, const SourcePosition& pos);
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& out, const SourcePositionInfo& pos);
1921cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& out,
1931cb0ef41Sopenharmony_ci                         const std::vector<SourcePositionInfo>& stack);
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci}  // namespace internal
1961cb0ef41Sopenharmony_ci}  // namespace v8
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_SOURCE_POSITION_H_
199