// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef V8_PROPERTY_H_
#define V8_PROPERTY_H_

#include "allocation.h"
#include "transitions.h"

namespace v8 {
namespace internal {


// Abstraction for elements in instance-descriptor arrays.
//
// Each descriptor has a key, property attributes, property type,
// property index (in the actual instance-descriptor array) and
// optionally a piece of data.
//

class Descriptor BASE_EMBEDDED {
 public:
  MUST_USE_RESULT MaybeObject* KeyToUniqueName() {
    if (!key_->IsUniqueName()) {
      MaybeObject* maybe_result =
          key_->GetIsolate()->heap()->InternalizeString(String::cast(key_));
      if (!maybe_result->To(&key_)) return maybe_result;
    }
    return key_;
  }

  Name* GetKey() { return key_; }
  Object* GetValue() { return value_; }
  PropertyDetails GetDetails() { return details_; }

#ifdef OBJECT_PRINT
  void Print(FILE* out);
#endif

  void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); }

 private:
  Name* key_;
  Object* value_;
  PropertyDetails details_;

 protected:
  Descriptor() : details_(Smi::FromInt(0)) {}

  void Init(Name* key, Object* value, PropertyDetails details) {
    key_ = key;
    value_ = value;
    details_ = details;
  }

  Descriptor(Name* key, Object* value, PropertyDetails details)
      : key_(key),
        value_(value),
        details_(details) { }

  Descriptor(Name* key,
             Object* value,
             PropertyAttributes attributes,
             PropertyType type,
             Representation representation,
             int field_index = 0)
      : key_(key),
        value_(value),
        details_(attributes, type, representation, field_index) { }

  friend class DescriptorArray;
};


class FieldDescriptor: public Descriptor {
 public:
  FieldDescriptor(Name* key,
                  int field_index,
                  PropertyAttributes attributes,
                  Representation representation)
      : Descriptor(key, Smi::FromInt(0), attributes,
                   FIELD, representation, field_index) {}
};


class ConstantDescriptor: public Descriptor {
 public:
  ConstantDescriptor(Name* key,
                     Object* value,
                     PropertyAttributes attributes)
      : Descriptor(key, value, attributes, CONSTANT,
                   value->OptimalRepresentation()) {}
};


class CallbacksDescriptor:  public Descriptor {
 public:
  CallbacksDescriptor(Name* key,
                      Object* foreign,
                      PropertyAttributes attributes)
      : Descriptor(key, foreign, attributes, CALLBACKS,
                   Representation::Tagged()) {}
};


// Holds a property index value distinguishing if it is a field index or an
// index inside the object header.
class PropertyIndex {
 public:
  static PropertyIndex NewFieldIndex(int index) {
    return PropertyIndex(index, false);
  }
  static PropertyIndex NewHeaderIndex(int index) {
    return PropertyIndex(index, true);
  }

  bool is_field_index() { return (index_ & kHeaderIndexBit) == 0; }
  bool is_header_index() { return (index_ & kHeaderIndexBit) != 0; }

  int field_index() {
    ASSERT(is_field_index());
    return value();
  }
  int header_index() {
    ASSERT(is_header_index());
    return value();
  }

  bool is_inobject(Handle<JSObject> holder) {
    if (is_header_index()) return true;
    return field_index() < holder->map()->inobject_properties();
  }

  int translate(Handle<JSObject> holder) {
    if (is_header_index()) return header_index();
    int index = field_index() - holder->map()->inobject_properties();
    if (index >= 0) return index;
    return index + holder->map()->instance_size() / kPointerSize;
  }

 private:
  static const int kHeaderIndexBit = 1 << 31;
  static const int kIndexMask = ~kHeaderIndexBit;

  int value() { return index_ & kIndexMask; }

  PropertyIndex(int index, bool is_header_based)
      : index_(index | (is_header_based ? kHeaderIndexBit : 0)) {
    ASSERT(index <= kIndexMask);
  }

  int index_;
};


class LookupResult BASE_EMBEDDED {
 public:
  explicit LookupResult(Isolate* isolate)
      : isolate_(isolate),
        next_(isolate->top_lookup_result()),
        lookup_type_(NOT_FOUND),
        holder_(NULL),
        cacheable_(true),
        details_(NONE, NONEXISTENT, Representation::None()) {
    isolate->SetTopLookupResult(this);
  }

  ~LookupResult() {
    ASSERT(isolate()->top_lookup_result() == this);
    isolate()->SetTopLookupResult(next_);
  }

  Isolate* isolate() const { return isolate_; }

  void DescriptorResult(JSObject* holder, PropertyDetails details, int number) {
    lookup_type_ = DESCRIPTOR_TYPE;
    holder_ = holder;
    details_ = details;
    number_ = number;
  }

  bool CanHoldValue(Handle<Object> value) {
    if (IsNormal()) return true;
    ASSERT(!IsTransition());
    return value->FitsRepresentation(details_.representation());
  }

  void TransitionResult(JSObject* holder, int number) {
    lookup_type_ = TRANSITION_TYPE;
    details_ = PropertyDetails(NONE, TRANSITION, Representation::None());
    holder_ = holder;
    number_ = number;
  }

  void DictionaryResult(JSObject* holder, int entry) {
    lookup_type_ = DICTIONARY_TYPE;
    holder_ = holder;
    details_ = holder->property_dictionary()->DetailsAt(entry);
    number_ = entry;
  }

  void HandlerResult(JSProxy* proxy) {
    lookup_type_ = HANDLER_TYPE;
    holder_ = proxy;
    details_ = PropertyDetails(NONE, HANDLER, Representation::Tagged());
    cacheable_ = false;
  }

  void InterceptorResult(JSObject* holder) {
    lookup_type_ = INTERCEPTOR_TYPE;
    holder_ = holder;
    details_ = PropertyDetails(NONE, INTERCEPTOR, Representation::Tagged());
  }

  void NotFound() {
    lookup_type_ = NOT_FOUND;
    details_ = PropertyDetails(NONE, NONEXISTENT, Representation::None());
    holder_ = NULL;
  }

  JSObject* holder() {
    ASSERT(IsFound());
    return JSObject::cast(holder_);
  }

  JSProxy* proxy() {
    ASSERT(IsFound());
    return JSProxy::cast(holder_);
  }

  PropertyType type() {
    ASSERT(IsFound());
    return details_.type();
  }

  Representation representation() {
    ASSERT(IsFound());
    ASSERT(!IsTransition());
    ASSERT(details_.type() != NONEXISTENT);
    return details_.representation();
  }

  PropertyAttributes GetAttributes() {
    ASSERT(!IsTransition());
    ASSERT(IsFound());
    ASSERT(details_.type() != NONEXISTENT);
    return details_.attributes();
  }

  PropertyDetails GetPropertyDetails() {
    ASSERT(!IsTransition());
    return details_;
  }

  bool IsFastPropertyType() {
    ASSERT(IsFound());
    return IsTransition() || type() != NORMAL;
  }

  // Property callbacks does not include transitions to callbacks.
  bool IsPropertyCallbacks() {
    ASSERT(!(details_.type() == CALLBACKS && !IsFound()));
    return details_.type() == CALLBACKS;
  }

  bool IsReadOnly() {
    ASSERT(IsFound());
    ASSERT(!IsTransition());
    ASSERT(details_.type() != NONEXISTENT);
    return details_.IsReadOnly();
  }

  bool IsField() {
    ASSERT(!(details_.type() == FIELD && !IsFound()));
    return details_.type() == FIELD;
  }

  bool IsNormal() {
    ASSERT(!(details_.type() == NORMAL && !IsFound()));
    return details_.type() == NORMAL;
  }

  bool IsConstant() {
    ASSERT(!(details_.type() == CONSTANT && !IsFound()));
    return details_.type() == CONSTANT;
  }

  bool IsConstantFunction() {
    return IsConstant() && GetValue()->IsJSFunction();
  }

  bool IsDontDelete() { return details_.IsDontDelete(); }
  bool IsDontEnum() { return details_.IsDontEnum(); }
  bool IsFound() { return lookup_type_ != NOT_FOUND; }
  bool IsTransition() { return lookup_type_ == TRANSITION_TYPE; }
  bool IsHandler() { return lookup_type_ == HANDLER_TYPE; }
  bool IsInterceptor() { return lookup_type_ == INTERCEPTOR_TYPE; }

  // Is the result is a property excluding transitions and the null descriptor?
  bool IsProperty() {
    return IsFound() && !IsTransition();
  }

  bool IsDataProperty() {
    switch (type()) {
      case FIELD:
      case NORMAL:
      case CONSTANT:
        return true;
      case CALLBACKS: {
        Object* callback = GetCallbackObject();
        return callback->IsAccessorInfo() || callback->IsForeign();
      }
      case HANDLER:
      case INTERCEPTOR:
      case TRANSITION:
      case NONEXISTENT:
        return false;
    }
    UNREACHABLE();
    return false;
  }

  bool IsCacheable() { return cacheable_; }
  void DisallowCaching() { cacheable_ = false; }

  Object* GetLazyValue() {
    switch (type()) {
      case FIELD:
        return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
      case NORMAL: {
        Object* value;
        value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
        if (holder()->IsGlobalObject()) {
          value = PropertyCell::cast(value)->value();
        }
        return value;
      }
      case CONSTANT:
        return GetConstant();
      case CALLBACKS:
      case HANDLER:
      case INTERCEPTOR:
      case TRANSITION:
      case NONEXISTENT:
        return isolate()->heap()->the_hole_value();
    }
    UNREACHABLE();
    return NULL;
  }

  Map* GetTransitionTarget(Map* map) {
    ASSERT(IsTransition());
    TransitionArray* transitions = map->transitions();
    return transitions->GetTarget(number_);
  }

  Map* GetTransitionTarget() {
    return GetTransitionTarget(holder()->map());
  }

  PropertyDetails GetTransitionDetails(Map* map) {
    ASSERT(IsTransition());
    TransitionArray* transitions = map->transitions();
    return transitions->GetTargetDetails(number_);
  }

  PropertyDetails GetTransitionDetails() {
    return GetTransitionDetails(holder()->map());
  }

  bool IsTransitionToField(Map* map) {
    return IsTransition() && GetTransitionDetails(map).type() == FIELD;
  }

  bool IsTransitionToConstant(Map* map) {
    return IsTransition() && GetTransitionDetails(map).type() == CONSTANT;
  }

  Map* GetTransitionMap() {
    ASSERT(IsTransition());
    return Map::cast(GetValue());
  }

  Map* GetTransitionMapFromMap(Map* map) {
    ASSERT(IsTransition());
    return map->transitions()->GetTarget(number_);
  }

  int GetTransitionIndex() {
    ASSERT(IsTransition());
    return number_;
  }

  int GetDescriptorIndex() {
    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
    return number_;
  }

  PropertyIndex GetFieldIndex() {
    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
    return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map()));
  }

  int GetLocalFieldIndexFromMap(Map* map) {
    return GetFieldIndexFromMap(map) - map->inobject_properties();
  }

  int GetDictionaryEntry() {
    ASSERT(lookup_type_ == DICTIONARY_TYPE);
    return number_;
  }

  JSFunction* GetConstantFunction() {
    ASSERT(type() == CONSTANT);
    return JSFunction::cast(GetValue());
  }

  Object* GetConstantFromMap(Map* map) {
    ASSERT(type() == CONSTANT);
    return GetValueFromMap(map);
  }

  JSFunction* GetConstantFunctionFromMap(Map* map) {
    return JSFunction::cast(GetConstantFromMap(map));
  }

  Object* GetConstant() {
    ASSERT(type() == CONSTANT);
    return GetValue();
  }

  Object* GetCallbackObject() {
    ASSERT(type() == CALLBACKS && !IsTransition());
    return GetValue();
  }

#ifdef OBJECT_PRINT
  void Print(FILE* out);
#endif

  Object* GetValue() {
    if (lookup_type_ == DESCRIPTOR_TYPE) {
      return GetValueFromMap(holder()->map());
    }
    // In the dictionary case, the data is held in the value field.
    ASSERT(lookup_type_ == DICTIONARY_TYPE);
    return holder()->GetNormalizedProperty(this);
  }

  Object* GetValueFromMap(Map* map) const {
    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
    ASSERT(number_ < map->NumberOfOwnDescriptors());
    return map->instance_descriptors()->GetValue(number_);
  }

  int GetFieldIndexFromMap(Map* map) const {
    ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
    ASSERT(number_ < map->NumberOfOwnDescriptors());
    return map->instance_descriptors()->GetFieldIndex(number_);
  }

  void Iterate(ObjectVisitor* visitor);

 private:
  Isolate* isolate_;
  LookupResult* next_;

  // Where did we find the result;
  enum {
    NOT_FOUND,
    DESCRIPTOR_TYPE,
    TRANSITION_TYPE,
    DICTIONARY_TYPE,
    HANDLER_TYPE,
    INTERCEPTOR_TYPE
  } lookup_type_;

  JSReceiver* holder_;
  int number_;
  bool cacheable_;
  PropertyDetails details_;
};


} }  // namespace v8::internal

#endif  // V8_PROPERTY_H_
