label.h 3.21 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// Copyright 2017 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_LABEL_H_
#define V8_LABEL_H_

#include "src/base/macros.h"

namespace v8 {
namespace internal {

// -----------------------------------------------------------------------------
// Labels represent pc locations; they are typically jump or call targets.
// After declaration, a label can be freely used to denote known or (yet)
// unknown pc location. Assembler::bind() is used to bind a label to the
// current pc. A label can be bound only once.

class Label {
 public:
21 22 23 24
  enum Distance {
    kNear,  // near jump: 8 bit displacement (signed)
    kFar    // far jump: 32 bit displacement (signed)
  };
25

26 27 28 29 30 31 32 33 34
  Label() = default;

// On ARM64, the Assembler keeps track of pointers to Labels to resolve
// branches to distant targets. Copying labels would confuse the Assembler.
// On other platforms, allow move construction.
#if !V8_TARGET_ARCH_ARM64
// In debug builds, the old Label has to be cleared in order to avoid a DCHECK
// failure in it's destructor.
#ifdef DEBUG
35 36
  Label(Label&& other) V8_NOEXCEPT { *this = std::move(other); }
  Label& operator=(Label&& other) V8_NOEXCEPT {
37 38 39 40 41
    pos_ = other.pos_;
    near_link_pos_ = other.near_link_pos_;
    other.Unuse();
    other.UnuseNear();
    return *this;
42
  }
43
#else
44 45
  Label(Label&&) V8_NOEXCEPT = default;
  Label& operator=(Label&&) V8_NOEXCEPT = default;
46 47
#endif
#endif
48

49
#ifdef DEBUG
50
  V8_INLINE ~Label() {
51 52 53
    DCHECK(!is_linked());
    DCHECK(!is_near_linked());
  }
54
#endif
55

56 57
  V8_INLINE void Unuse() { pos_ = 0; }
  V8_INLINE void UnuseNear() { near_link_pos_ = 0; }
58

59 60 61 62
  V8_INLINE bool is_bound() const { return pos_ < 0; }
  V8_INLINE bool is_unused() const { return pos_ == 0 && near_link_pos_ == 0; }
  V8_INLINE bool is_linked() const { return pos_ > 0; }
  V8_INLINE bool is_near_linked() const { return near_link_pos_ > 0; }
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

  // Returns the position of bound or linked labels. Cannot be used
  // for unused labels.
  int pos() const {
    if (pos_ < 0) return -pos_ - 1;
    if (pos_ > 0) return pos_ - 1;
    UNREACHABLE();
  }

  int near_link_pos() const { return near_link_pos_ - 1; }

 private:
  // pos_ encodes both the binding state (via its sign)
  // and the binding position (via its value) of a label.
  //
  // pos_ <  0  bound label, pos() returns the jump target position
  // pos_ == 0  unused label
  // pos_ >  0  linked label, pos() returns the last reference position
81
  int pos_ = 0;
82 83

  // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
84
  int near_link_pos_ = 0;
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

  void bind_to(int pos) {
    pos_ = -pos - 1;
    DCHECK(is_bound());
  }
  void link_to(int pos, Distance distance = kFar) {
    if (distance == kNear) {
      near_link_pos_ = pos + 1;
      DCHECK(is_near_linked());
    } else {
      pos_ = pos + 1;
      DCHECK(is_linked());
    }
  }

  friend class Assembler;
  friend class Displacement;
  friend class RegExpMacroAssemblerIrregexp;

104 105 106
  // Disallow copy construction and assignment, but allow move construction and
  // move assignment on selected platforms (see above).
  DISALLOW_COPY_AND_ASSIGN(Label);
107 108 109 110 111 112
};

}  // namespace internal
}  // namespace v8

#endif  // V8_LABEL_H_