// Copyright 2019 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_OBJECTS_TAGGED_IMPL_INL_H_
#define V8_OBJECTS_TAGGED_IMPL_INL_H_

#include "src/objects/tagged-impl.h"

#ifdef V8_COMPRESS_POINTERS
#include "src/execution/isolate.h"
#endif
#include "src/common/ptr-compr-inl.h"
#include "src/objects/heap-object.h"
#include "src/objects/smi.h"
#include "src/roots/roots-inl.h"

namespace v8 {
namespace internal {

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::ToSmi(Smi* value) const {
  if (HAS_SMI_TAG(ptr_)) {
    *value = ToSmi();
    return true;
  }
  return false;
}

template <HeapObjectReferenceType kRefType, typename StorageType>
Smi TaggedImpl<kRefType, StorageType>::ToSmi() const {
  DCHECK(HAS_SMI_TAG(ptr_));
  if (kIsFull) {
    return Smi(ptr_);
  }
  // Implementation for compressed pointers.
  return Smi(DecompressTaggedSigned(static_cast<Tagged_t>(ptr_)));
}

//
// TaggedImpl::GetHeapObject(HeapObject* result) implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
    HeapObject* result) const {
  CHECK(kIsFull);
  if (!IsStrongOrWeak()) return false;
  *result = GetHeapObject();
  return true;
}

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
    Isolate* isolate, HeapObject* result) const {
  if (kIsFull) return GetHeapObject(result);
  // Implementation for compressed pointers.
  if (!IsStrongOrWeak()) return false;
  *result = GetHeapObject(isolate);
  return true;
}

//
// TaggedImpl::GetHeapObject(HeapObject* result,
//                           HeapObjectReferenceType* reference_type)
// implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
    HeapObject* result, HeapObjectReferenceType* reference_type) const {
  CHECK(kIsFull);
  if (!IsStrongOrWeak()) return false;
  *reference_type = IsWeakOrCleared() ? HeapObjectReferenceType::WEAK
                                      : HeapObjectReferenceType::STRONG;
  *result = GetHeapObject();
  return true;
}

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObject(
    Isolate* isolate, HeapObject* result,
    HeapObjectReferenceType* reference_type) const {
  if (kIsFull) return GetHeapObject(result, reference_type);
  // Implementation for compressed pointers.
  if (!IsStrongOrWeak()) return false;
  *reference_type = IsWeakOrCleared() ? HeapObjectReferenceType::WEAK
                                      : HeapObjectReferenceType::STRONG;
  *result = GetHeapObject(isolate);
  return true;
}

//
// TaggedImpl::GetHeapObjectIfStrong(HeapObject* result) implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfStrong(
    HeapObject* result) const {
  CHECK(kIsFull);
  if (IsStrong()) {
    *result = HeapObject::cast(Object(ptr_));
    return true;
  }
  return false;
}

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfStrong(
    Isolate* isolate, HeapObject* result) const {
  if (kIsFull) return GetHeapObjectIfStrong(result);
  // Implementation for compressed pointers.
  if (IsStrong()) {
    *result = HeapObject::cast(
        Object(DecompressTaggedPointer(isolate, static_cast<Tagged_t>(ptr_))));
    return true;
  }
  return false;
}

//
// TaggedImpl::GetHeapObjectAssumeStrong() implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeStrong()
    const {
  CHECK(kIsFull);
  DCHECK(IsStrong());
  return HeapObject::cast(Object(ptr_));
}

template <HeapObjectReferenceType kRefType, typename StorageType>
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeStrong(
    Isolate* isolate) const {
  if (kIsFull) return GetHeapObjectAssumeStrong();
  // Implementation for compressed pointers.
  DCHECK(IsStrong());
  return HeapObject::cast(
      Object(DecompressTaggedPointer(isolate, static_cast<Tagged_t>(ptr_))));
}

//
// TaggedImpl::GetHeapObjectIfWeak(HeapObject* result) implementation
//

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfWeak(
    HeapObject* result) const {
  CHECK(kIsFull);
  if (kCanBeWeak) {
    if (IsWeak()) {
      *result = GetHeapObject();
      return true;
    }
    return false;
  } else {
    DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
    return false;
  }
}

template <HeapObjectReferenceType kRefType, typename StorageType>
bool TaggedImpl<kRefType, StorageType>::GetHeapObjectIfWeak(
    Isolate* isolate, HeapObject* result) const {
  if (kIsFull) return GetHeapObjectIfWeak(result);
  // Implementation for compressed pointers.
  if (kCanBeWeak) {
    if (IsWeak()) {
      *result = GetHeapObject(isolate);
      return true;
    }
    return false;
  } else {
    DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
    return false;
  }
}

//
// TaggedImpl::GetHeapObjectAssumeWeak() implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeWeak() const {
  CHECK(kIsFull);
  DCHECK(IsWeak());
  return GetHeapObject();
}

template <HeapObjectReferenceType kRefType, typename StorageType>
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObjectAssumeWeak(
    Isolate* isolate) const {
  if (kIsFull) return GetHeapObjectAssumeWeak();
  // Implementation for compressed pointers.
  DCHECK(IsWeak());
  return GetHeapObject(isolate);
}

//
// TaggedImpl::GetHeapObject() implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObject() const {
  CHECK(kIsFull);
  DCHECK(!IsSmi());
  if (kCanBeWeak) {
    DCHECK(!IsCleared());
    return HeapObject::cast(Object(ptr_ & ~kWeakHeapObjectMask));
  } else {
    DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
    return HeapObject::cast(Object(ptr_));
  }
}

template <HeapObjectReferenceType kRefType, typename StorageType>
HeapObject TaggedImpl<kRefType, StorageType>::GetHeapObject(
    Isolate* isolate) const {
  if (kIsFull) return GetHeapObject();
  // Implementation for compressed pointers.
  DCHECK(!IsSmi());
  if (kCanBeWeak) {
    DCHECK(!IsCleared());
    return HeapObject::cast(Object(DecompressTaggedPointer(
        isolate, static_cast<Tagged_t>(ptr_) & ~kWeakHeapObjectMask)));
  } else {
    DCHECK(!HAS_WEAK_HEAP_OBJECT_TAG(ptr_));
    return HeapObject::cast(
        Object(DecompressTaggedPointer(isolate, static_cast<Tagged_t>(ptr_))));
  }
}

//
// TaggedImpl::GetHeapObjectOrSmi() implementation.
//

template <HeapObjectReferenceType kRefType, typename StorageType>
Object TaggedImpl<kRefType, StorageType>::GetHeapObjectOrSmi() const {
  CHECK(kIsFull);
  if (IsSmi()) {
    return Object(ptr_);
  }
  return GetHeapObject();
}

template <HeapObjectReferenceType kRefType, typename StorageType>
Object TaggedImpl<kRefType, StorageType>::GetHeapObjectOrSmi(
    Isolate* isolate) const {
  if (kIsFull) return GetHeapObjectOrSmi();
  // Implementation for compressed pointers.
  if (IsSmi()) {
    return Object(DecompressTaggedSigned(static_cast<Tagged_t>(ptr_)));
  }
  return GetHeapObject(isolate);
}

}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_TAGGED_IMPL_INL_H_
