// 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_OBJECTS_NAME_INL_H_
#define V8_OBJECTS_NAME_INL_H_

#include "src/objects/name.h"

#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/map-inl.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

OBJECT_CONSTRUCTORS_IMPL(Name, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(Symbol, Name)

CAST_ACCESSOR(Name)
CAST_ACCESSOR(Symbol)

ACCESSORS(Symbol, name, Object, kNameOffset)
INT_ACCESSORS(Symbol, flags, kFlagsOffset)
BIT_FIELD_ACCESSORS(Symbol, flags, is_private, Symbol::IsPrivateBit)
BIT_FIELD_ACCESSORS(Symbol, flags, is_well_known_symbol,
                    Symbol::IsWellKnownSymbolBit)
BIT_FIELD_ACCESSORS(Symbol, flags, is_public, Symbol::IsPublicBit)
BIT_FIELD_ACCESSORS(Symbol, flags, is_interesting_symbol,
                    Symbol::IsInterestingSymbolBit)

bool Symbol::is_private_name() const {
  bool value = Symbol::IsPrivateNameBit::decode(flags());
  DCHECK_IMPLIES(value, is_private());
  return value;
}

void Symbol::set_is_private_name() {
  // TODO(gsathya): Re-order the bits to have these next to each other
  // and just do the bit shifts once.
  set_flags(Symbol::IsPrivateBit::update(flags(), true));
  set_flags(Symbol::IsPrivateNameBit::update(flags(), true));
}

bool Name::IsUniqueName() const {
  uint32_t type = map()->instance_type();
  bool result = (type & (kIsNotStringMask | kIsNotInternalizedMask)) !=
                (kStringTag | kNotInternalizedTag);
  SLOW_DCHECK(result == HeapObject::IsUniqueName());
  return result;
}

uint32_t Name::hash_field() {
  return READ_UINT32_FIELD(*this, kHashFieldOffset);
}

void Name::set_hash_field(uint32_t value) {
  WRITE_UINT32_FIELD(*this, kHashFieldOffset, value);
}

bool Name::Equals(Name other) {
  if (other == *this) return true;
  if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
      this->IsSymbol() || other->IsSymbol()) {
    return false;
  }
  return String::cast(*this)->SlowEquals(String::cast(other));
}

bool Name::Equals(Isolate* isolate, Handle<Name> one, Handle<Name> two) {
  if (one.is_identical_to(two)) return true;
  if ((one->IsInternalizedString() && two->IsInternalizedString()) ||
      one->IsSymbol() || two->IsSymbol()) {
    return false;
  }
  return String::SlowEquals(isolate, Handle<String>::cast(one),
                            Handle<String>::cast(two));
}

bool Name::IsHashFieldComputed(uint32_t field) {
  return (field & kHashNotComputedMask) == 0;
}

bool Name::HasHashCode() { return IsHashFieldComputed(hash_field()); }

uint32_t Name::Hash() {
  // Fast case: has hash code already been computed?
  uint32_t field = hash_field();
  if (IsHashFieldComputed(field)) return field >> kHashShift;
  // Slow case: compute hash code and set it. Has to be a string.
  return String::cast(*this)->ComputeAndSetHash();
}

bool Name::IsInterestingSymbol() const {
  return IsSymbol() && Symbol::cast(*this)->is_interesting_symbol();
}

bool Name::IsPrivate() {
  return this->IsSymbol() && Symbol::cast(*this)->is_private();
}

bool Name::IsPrivateName() {
  bool is_private_name =
      this->IsSymbol() && Symbol::cast(*this)->is_private_name();
  DCHECK_IMPLIES(is_private_name, IsPrivate());
  return is_private_name;
}

bool Name::AsArrayIndex(uint32_t* index) {
  return IsString() && String::cast(*this)->AsArrayIndex(index);
}

// static
bool Name::ContainsCachedArrayIndex(uint32_t hash) {
  return (hash & Name::kDoesNotContainCachedArrayIndexMask) == 0;
}

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_NAME_INL_H_
