ptr-compr-inl.h 8.4 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2018 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_PTR_COMPR_INL_H_
#define V8_PTR_COMPR_INL_H_

#if V8_TARGET_ARCH_64_BIT

10
#include "src/objects/heap-object-inl.h"
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#include "src/ptr-compr.h"

namespace v8 {
namespace internal {

// Compresses full-pointer representation of a tagged value to on-heap
// representation.
V8_INLINE Tagged_t CompressTagged(Address tagged) {
  // The compression is no-op while we are using checked decompression.
  STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
  // TODO(ishell): implement once kTaggedSize is equal to kInt32Size.
  return tagged;
}

// Calculates isolate root value from any on-heap address.
V8_INLINE Address GetRootFromOnHeapAddress(Address addr) {
  return RoundDown(addr + kPtrComprIsolateRootBias,
                   kPtrComprIsolateRootAlignment);
}

// Decompresses weak or strong heap object pointer or forwarding pointer,
// preserving both weak- and smi- tags.
V8_INLINE Address DecompressTaggedPointerImpl(Address on_heap_addr,
                                              int32_t value) {
  Address root = GetRootFromOnHeapAddress(on_heap_addr);
  // Current compression scheme requires value to be sign-extended to inptr_t
  // before adding the |root|.
  return root + static_cast<Address>(static_cast<intptr_t>(value));
}

// Decompresses weak or strong heap object pointer or forwarding pointer,
// preserving both weak- and smi- tags and checks that the result of
// decompression matches full value stored in the field.
// Checked decompression helps to find misuses of XxxSlots and FullXxxSlots.
// TODO(ishell): remove in favour of DecompressTaggedPointerImpl() once
// kTaggedSize is equal to kInt32Size.
V8_INLINE Address DecompressTaggedPointer(Address on_heap_addr,
                                          Tagged_t full_value) {
  // Use only lower 32-bits of the value for decompression.
  int32_t compressed = static_cast<int32_t>(full_value);
  STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
  Address result = DecompressTaggedPointerImpl(on_heap_addr, compressed);
#ifdef DEBUG
  if (full_value != result) {
    base::OS::DebugBreak();
    result = DecompressTaggedPointerImpl(on_heap_addr, compressed);
  }
#endif
  DCHECK_EQ(full_value, result);
  return result;
}

// Decompresses any tagged value, preserving both weak- and smi- tags.
V8_INLINE Address DecompressTaggedAnyImpl(Address on_heap_addr, int32_t value) {
  // |root_mask| is 0 if the |value| was a smi or -1 otherwise.
  Address root_mask = -static_cast<Address>(value & kSmiTagMask);
  Address root_or_zero = root_mask & GetRootFromOnHeapAddress(on_heap_addr);
  // Current compression scheme requires value to be sign-extended to inptr_t
  // before adding the |root_or_zero|.
  return root_or_zero + static_cast<Address>(static_cast<intptr_t>(value));
}

// Decompresses any tagged value, preserving both weak- and smi- tags and checks
// that the result of decompression matches full value stored in the field.
// Checked decompression helps to find misuses of XxxSlots and FullXxxSlots.
// TODO(ishell): remove in favour of DecompressTaggedAnyImpl() once
// kTaggedSize is equal to kInt32Size.
V8_INLINE Address DecompressTaggedAny(Address on_heap_addr,
                                      Tagged_t full_value) {
  // Use only lower 32-bits of the value for decompression.
  int32_t compressed = static_cast<int32_t>(full_value);
  STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
  Address result = DecompressTaggedAnyImpl(on_heap_addr, compressed);
#ifdef DEBUG
  if (full_value != result) {
    base::OS::DebugBreak();
    result = DecompressTaggedAnyImpl(on_heap_addr, compressed);
  }
#endif
  DCHECK_EQ(full_value, result);
  return result;
}

//
// CompressedObjectSlot implementation.
//

98
CompressedObjectSlot::CompressedObjectSlot(Object* object)
99 100
    : SlotBase(reinterpret_cast<Address>(&object->ptr_)) {}

101
Object CompressedObjectSlot::operator*() const {
102
  Tagged_t value = *location();
103
  return Object(DecompressTaggedAny(address(), value));
104 105
}

106
void CompressedObjectSlot::store(Object value) const {
107 108 109
  *location() = CompressTagged(value->ptr());
}

110
Object CompressedObjectSlot::Acquire_Load() const {
111
  AtomicTagged_t value = AsAtomicTagged::Acquire_Load(location());
112
  return Object(DecompressTaggedAny(address(), value));
113 114
}

115
Object CompressedObjectSlot::Relaxed_Load() const {
116
  AtomicTagged_t value = AsAtomicTagged::Relaxed_Load(location());
117
  return Object(DecompressTaggedAny(address(), value));
118 119
}

120
void CompressedObjectSlot::Relaxed_Store(Object value) const {
121 122 123 124
  Tagged_t ptr = CompressTagged(value->ptr());
  AsAtomicTagged::Relaxed_Store(location(), ptr);
}

125
void CompressedObjectSlot::Release_Store(Object value) const {
126 127 128 129
  Tagged_t ptr = CompressTagged(value->ptr());
  AsAtomicTagged::Release_Store(location(), ptr);
}

130 131
Object CompressedObjectSlot::Release_CompareAndSwap(Object old,
                                                    Object target) const {
132 133 134 135
  Tagged_t old_ptr = CompressTagged(old->ptr());
  Tagged_t target_ptr = CompressTagged(target->ptr());
  Tagged_t result =
      AsAtomicTagged::Release_CompareAndSwap(location(), old_ptr, target_ptr);
136
  return Object(DecompressTaggedAny(address(), result));
137 138 139 140 141 142 143 144 145 146 147
}

//
// CompressedMapWordSlot implementation.
//

bool CompressedMapWordSlot::contains_value(Address raw_value) const {
  Tagged_t value = *location();
  return value == static_cast<Tagged_t>(raw_value);
}

148
Object CompressedMapWordSlot::operator*() const {
149
  Tagged_t value = *location();
150
  return Object(DecompressTaggedPointer(address(), value));
151 152
}

153
void CompressedMapWordSlot::store(Object value) const {
154 155 156
  *location() = CompressTagged(value.ptr());
}

157
Object CompressedMapWordSlot::Relaxed_Load() const {
158
  AtomicTagged_t value = AsAtomicTagged::Relaxed_Load(location());
159
  return Object(DecompressTaggedPointer(address(), value));
160 161
}

162
void CompressedMapWordSlot::Relaxed_Store(Object value) const {
163 164 165 166
  Tagged_t ptr = CompressTagged(value.ptr());
  AsAtomicTagged::Relaxed_Store(location(), ptr);
}

167
Object CompressedMapWordSlot::Acquire_Load() const {
168
  AtomicTagged_t value = AsAtomicTagged::Acquire_Load(location());
169
  return Object(DecompressTaggedPointer(address(), value));
170 171
}

172
void CompressedMapWordSlot::Release_Store(Object value) const {
173 174 175 176
  Tagged_t ptr = CompressTagged(value->ptr());
  AsAtomicTagged::Release_Store(location(), ptr);
}

177 178
Object CompressedMapWordSlot::Release_CompareAndSwap(Object old,
                                                     Object target) const {
179 180 181 182
  Tagged_t old_ptr = CompressTagged(old->ptr());
  Tagged_t target_ptr = CompressTagged(target->ptr());
  Tagged_t result =
      AsAtomicTagged::Release_CompareAndSwap(location(), old_ptr, target_ptr);
183
  return Object(DecompressTaggedPointer(address(), result));
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
}

//
// CompressedMaybeObjectSlot implementation.
//

MaybeObject CompressedMaybeObjectSlot::operator*() const {
  Tagged_t value = *location();
  return MaybeObject(DecompressTaggedAny(address(), value));
}

void CompressedMaybeObjectSlot::store(MaybeObject value) const {
  *location() = CompressTagged(value->ptr());
}

MaybeObject CompressedMaybeObjectSlot::Relaxed_Load() const {
  AtomicTagged_t value = AsAtomicTagged::Relaxed_Load(location());
  return MaybeObject(DecompressTaggedAny(address(), value));
}

void CompressedMaybeObjectSlot::Relaxed_Store(MaybeObject value) const {
  Tagged_t ptr = CompressTagged(value->ptr());
  AsAtomicTagged::Relaxed_Store(location(), ptr);
}

void CompressedMaybeObjectSlot::Release_CompareAndSwap(
    MaybeObject old, MaybeObject target) const {
  Tagged_t old_ptr = CompressTagged(old->ptr());
  Tagged_t target_ptr = CompressTagged(target->ptr());
  AsAtomicTagged::Release_CompareAndSwap(location(), old_ptr, target_ptr);
}

//
// CompressedHeapObjectSlot implementation.
//

HeapObjectReference CompressedHeapObjectSlot::operator*() const {
  Tagged_t value = *location();
  return HeapObjectReference(DecompressTaggedPointer(address(), value));
}

void CompressedHeapObjectSlot::store(HeapObjectReference value) const {
  *location() = CompressTagged(value.ptr());
}

229 230
HeapObject CompressedHeapObjectSlot::ToHeapObject() const {
  DCHECK((*location() & kHeapObjectTagMask) == kHeapObjectTag);
231
  return HeapObject::cast(Object(*location()));
232 233 234 235 236 237
}

void CompressedHeapObjectSlot::StoreHeapObject(HeapObject value) const {
  *location() = value->ptr();
}

238 239 240 241 242 243
}  // namespace internal
}  // namespace v8

#endif  // V8_TARGET_ARCH_64_BIT

#endif  // V8_PTR_COMPR_INL_H_