// Copyright 2014 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_TYPES_INL_H_
#define V8_TYPES_INL_H_

#include "src/types.h"

#include "src/factory.h"
#include "src/handles-inl.h"

namespace v8 {
namespace internal {

// -----------------------------------------------------------------------------
// TypeImpl

template<class Config>
TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
  TypeImpl* t = static_cast<TypeImpl*>(object);
  DCHECK(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsRange() ||
         t->IsUnion() || t->IsArray() || t->IsFunction() || t->IsContext());
  return t;
}


// Most precise _current_ type of a value (usually its class).
template<class Config>
typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NowOf(
    i::Object* value, Region* region) {
  if (value->IsSmi() ||
      i::HeapObject::cast(value)->map()->instance_type() == HEAP_NUMBER_TYPE) {
    return Of(value, region);
  }
  return Class(i::handle(i::HeapObject::cast(value)->map()), region);
}


template<class Config>
bool TypeImpl<Config>::NowContains(i::Object* value) {
  DisallowHeapAllocation no_allocation;
  if (this->IsAny()) return true;
  if (value->IsHeapObject()) {
    i::Map* map = i::HeapObject::cast(value)->map();
    for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
      if (*it.Current() == map) return true;
    }
  }
  return this->Contains(value);
}


// -----------------------------------------------------------------------------
// ZoneTypeConfig

// static
template<class T>
T* ZoneTypeConfig::handle(T* type) {
  return type;
}


// static
template<class T>
T* ZoneTypeConfig::cast(Type* type) {
  return static_cast<T*>(type);
}


// static
bool ZoneTypeConfig::is_bitset(Type* type) {
  return reinterpret_cast<intptr_t>(type) & 1;
}


// static
bool ZoneTypeConfig::is_struct(Type* type, int tag) {
  return !is_bitset(type) && struct_tag(as_struct(type)) == tag;
}


// static
bool ZoneTypeConfig::is_class(Type* type) {
  return false;
}


// static
int ZoneTypeConfig::as_bitset(Type* type) {
  DCHECK(is_bitset(type));
  return static_cast<int>(reinterpret_cast<intptr_t>(type) >> 1);
}


// static
ZoneTypeConfig::Struct* ZoneTypeConfig::as_struct(Type* type) {
  DCHECK(!is_bitset(type));
  return reinterpret_cast<Struct*>(type);
}


// static
i::Handle<i::Map> ZoneTypeConfig::as_class(Type* type) {
  UNREACHABLE();
  return i::Handle<i::Map>();
}


// static
ZoneTypeConfig::Type* ZoneTypeConfig::from_bitset(int bitset) {
  return reinterpret_cast<Type*>((bitset << 1) | 1);
}


// static
ZoneTypeConfig::Type* ZoneTypeConfig::from_bitset(int bitset, Zone* Zone) {
  return from_bitset(bitset);
}


// static
ZoneTypeConfig::Type* ZoneTypeConfig::from_struct(Struct* structure) {
  return reinterpret_cast<Type*>(structure);
}


// static
ZoneTypeConfig::Type* ZoneTypeConfig::from_class(
    i::Handle<i::Map> map, Zone* zone) {
  return from_bitset(0);
}


// static
ZoneTypeConfig::Struct* ZoneTypeConfig::struct_create(
    int tag, int length, Zone* zone) {
  Struct* structure = reinterpret_cast<Struct*>(
      zone->New(sizeof(void*) * (length + 2)));  // NOLINT
  structure[0] = reinterpret_cast<void*>(tag);
  structure[1] = reinterpret_cast<void*>(length);
  return structure;
}


// static
void ZoneTypeConfig::struct_shrink(Struct* structure, int length) {
  DCHECK(0 <= length && length <= struct_length(structure));
  structure[1] = reinterpret_cast<void*>(length);
}


// static
int ZoneTypeConfig::struct_tag(Struct* structure) {
  return static_cast<int>(reinterpret_cast<intptr_t>(structure[0]));
}


// static
int ZoneTypeConfig::struct_length(Struct* structure) {
  return static_cast<int>(reinterpret_cast<intptr_t>(structure[1]));
}


// static
Type* ZoneTypeConfig::struct_get(Struct* structure, int i) {
  DCHECK(0 <= i && i <= struct_length(structure));
  return static_cast<Type*>(structure[2 + i]);
}


// static
void ZoneTypeConfig::struct_set(Struct* structure, int i, Type* x) {
  DCHECK(0 <= i && i <= struct_length(structure));
  structure[2 + i] = x;
}


// static
template<class V>
i::Handle<V> ZoneTypeConfig::struct_get_value(Struct* structure, int i) {
  DCHECK(0 <= i && i <= struct_length(structure));
  return i::Handle<V>(static_cast<V**>(structure[2 + i]));
}


// static
template<class V>
void ZoneTypeConfig::struct_set_value(
    Struct* structure, int i, i::Handle<V> x) {
  DCHECK(0 <= i && i <= struct_length(structure));
  structure[2 + i] = x.location();
}


// -----------------------------------------------------------------------------
// HeapTypeConfig

// static
template<class T>
i::Handle<T> HeapTypeConfig::handle(T* type) {
  return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
}


// static
template<class T>
i::Handle<T> HeapTypeConfig::cast(i::Handle<Type> type) {
  return i::Handle<T>::cast(type);
}


// static
bool HeapTypeConfig::is_bitset(Type* type) {
  return type->IsSmi();
}


// static
bool HeapTypeConfig::is_class(Type* type) {
  return type->IsMap();
}


// static
bool HeapTypeConfig::is_struct(Type* type, int tag) {
  return type->IsFixedArray() && struct_tag(as_struct(type)) == tag;
}


// static
int HeapTypeConfig::as_bitset(Type* type) {
  return i::Smi::cast(type)->value();
}


// static
i::Handle<i::Map> HeapTypeConfig::as_class(Type* type) {
  return i::handle(i::Map::cast(type));
}


// static
i::Handle<HeapTypeConfig::Struct> HeapTypeConfig::as_struct(Type* type) {
  return i::handle(Struct::cast(type));
}


// static
HeapTypeConfig::Type* HeapTypeConfig::from_bitset(int bitset) {
  return Type::cast(i::Smi::FromInt(bitset));
}


// static
i::Handle<HeapTypeConfig::Type> HeapTypeConfig::from_bitset(
    int bitset, Isolate* isolate) {
  return i::handle(from_bitset(bitset), isolate);
}


// static
i::Handle<HeapTypeConfig::Type> HeapTypeConfig::from_class(
    i::Handle<i::Map> map, Isolate* isolate) {
  return i::Handle<Type>::cast(i::Handle<Object>::cast(map));
}


// static
i::Handle<HeapTypeConfig::Type> HeapTypeConfig::from_struct(
    i::Handle<Struct> structure) {
  return i::Handle<Type>::cast(i::Handle<Object>::cast(structure));
}


// static
i::Handle<HeapTypeConfig::Struct> HeapTypeConfig::struct_create(
    int tag, int length, Isolate* isolate) {
  i::Handle<Struct> structure = isolate->factory()->NewFixedArray(length + 1);
  structure->set(0, i::Smi::FromInt(tag));
  return structure;
}


// static
void HeapTypeConfig::struct_shrink(i::Handle<Struct> structure, int length) {
  structure->Shrink(length + 1);
}


// static
int HeapTypeConfig::struct_tag(i::Handle<Struct> structure) {
  return static_cast<i::Smi*>(structure->get(0))->value();
}


// static
int HeapTypeConfig::struct_length(i::Handle<Struct> structure) {
  return structure->length() - 1;
}


// static
i::Handle<HeapTypeConfig::Type> HeapTypeConfig::struct_get(
    i::Handle<Struct> structure, int i) {
  Type* type = static_cast<Type*>(structure->get(i + 1));
  return i::handle(type, structure->GetIsolate());
}


// static
void HeapTypeConfig::struct_set(
    i::Handle<Struct> structure, int i, i::Handle<Type> type) {
  structure->set(i + 1, *type);
}


// static
template<class V>
i::Handle<V> HeapTypeConfig::struct_get_value(
    i::Handle<Struct> structure, int i) {
  V* x = static_cast<V*>(structure->get(i + 1));
  return i::handle(x, structure->GetIsolate());
}


// static
template<class V>
void HeapTypeConfig::struct_set_value(
    i::Handle<Struct> structure, int i, i::Handle<V> x) {
  structure->set(i + 1, *x);
}

} }  // namespace v8::internal

#endif  // V8_TYPES_INL_H_
