// Copyright 2015 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_COMPILER_ACCESS_INFO_H_
#define V8_COMPILER_ACCESS_INFO_H_

#include <iosfwd>

#include "src/field-index.h"
#include "src/machine-type.h"
#include "src/objects.h"
#include "src/objects/map.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {

// Forward declarations.
class CompilationDependencies;
class Factory;

namespace compiler {

// Forward declarations.
class Type;
class TypeCache;

// Whether we are loading a property or storing to a property.
// For a store during literal creation, do not walk up the prototype chain.
enum class AccessMode { kLoad, kStore, kStoreInLiteral };

std::ostream& operator<<(std::ostream&, AccessMode);

// Mapping of transition source to transition target.
typedef std::vector<std::pair<Handle<Map>, Handle<Map>>> MapTransitionList;

// This class encapsulates all information required to access a certain element.
class ElementAccessInfo final {
 public:
  ElementAccessInfo();
  ElementAccessInfo(MapHandles const& receiver_maps,
                    ElementsKind elements_kind);

  ElementsKind elements_kind() const { return elements_kind_; }
  MapHandles const& receiver_maps() const { return receiver_maps_; }
  MapTransitionList& transitions() { return transitions_; }
  MapTransitionList const& transitions() const { return transitions_; }

 private:
  ElementsKind elements_kind_;
  MapHandles receiver_maps_;
  MapTransitionList transitions_;
};

// This class encapsulates all information required to access a certain
// object property, either on the object itself or on the prototype chain.
class PropertyAccessInfo final {
 public:
  enum Kind {
    kInvalid,
    kNotFound,
    kDataConstant,
    kDataField,
    kDataConstantField,
    kAccessorConstant,
    kModuleExport
  };

  static PropertyAccessInfo NotFound(MapHandles const& receiver_maps,
                                     MaybeHandle<JSObject> holder);
  static PropertyAccessInfo DataConstant(MapHandles const& receiver_maps,
                                         Handle<Object> constant,
                                         MaybeHandle<JSObject> holder);
  static PropertyAccessInfo DataField(
      PropertyConstness constness, MapHandles const& receiver_maps,
      FieldIndex field_index, MachineRepresentation field_representation,
      Type* field_type, MaybeHandle<Map> field_map = MaybeHandle<Map>(),
      MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
      MaybeHandle<Map> transition_map = MaybeHandle<Map>());
  static PropertyAccessInfo AccessorConstant(MapHandles const& receiver_maps,
                                             Handle<Object> constant,
                                             MaybeHandle<JSObject> holder);
  static PropertyAccessInfo ModuleExport(MapHandles const& receiver_maps,
                                         Handle<Cell> cell);

  PropertyAccessInfo();

  bool Merge(PropertyAccessInfo const* that, AccessMode access_mode,
             Zone* zone) WARN_UNUSED_RESULT;

  bool IsNotFound() const { return kind() == kNotFound; }
  bool IsDataConstant() const { return kind() == kDataConstant; }
  bool IsDataField() const { return kind() == kDataField; }
  // TODO(ishell): rename to IsDataConstant() once constant field tracking
  // is done.
  bool IsDataConstantField() const { return kind() == kDataConstantField; }
  bool IsAccessorConstant() const { return kind() == kAccessorConstant; }
  bool IsModuleExport() const { return kind() == kModuleExport; }

  bool HasTransitionMap() const { return !transition_map().is_null(); }

  Kind kind() const { return kind_; }
  MaybeHandle<JSObject> holder() const { return holder_; }
  MaybeHandle<Map> transition_map() const { return transition_map_; }
  Handle<Object> constant() const { return constant_; }
  FieldIndex field_index() const { return field_index_; }
  Type* field_type() const { return field_type_; }
  MachineRepresentation field_representation() const {
    return field_representation_;
  }
  MaybeHandle<Map> field_map() const { return field_map_; }
  MapHandles const& receiver_maps() const { return receiver_maps_; }
  Handle<Cell> export_cell() const;

 private:
  PropertyAccessInfo(MaybeHandle<JSObject> holder,
                     MapHandles const& receiver_maps);
  PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
                     Handle<Object> constant, MapHandles const& receiver_maps);
  PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
                     MaybeHandle<Map> transition_map, FieldIndex field_index,
                     MachineRepresentation field_representation,
                     Type* field_type, MaybeHandle<Map> field_map,
                     MapHandles const& receiver_maps);

  Kind kind_;
  MapHandles receiver_maps_;
  Handle<Object> constant_;
  MaybeHandle<Map> transition_map_;
  MaybeHandle<JSObject> holder_;
  FieldIndex field_index_;
  MachineRepresentation field_representation_;
  Type* field_type_;
  MaybeHandle<Map> field_map_;
};


// Factory class for {ElementAccessInfo}s and {PropertyAccessInfo}s.
class AccessInfoFactory final {
 public:
  AccessInfoFactory(CompilationDependencies* dependencies,
                    Handle<Context> native_context, Zone* zone);

  bool ComputeElementAccessInfo(Handle<Map> map, AccessMode access_mode,
                                ElementAccessInfo* access_info);
  bool ComputeElementAccessInfos(MapHandles const& maps, AccessMode access_mode,
                                 ZoneVector<ElementAccessInfo>* access_infos);
  bool ComputePropertyAccessInfo(Handle<Map> map, Handle<Name> name,
                                 AccessMode access_mode,
                                 PropertyAccessInfo* access_info);
  bool ComputePropertyAccessInfos(MapHandles const& maps, Handle<Name> name,
                                  AccessMode access_mode,
                                  ZoneVector<PropertyAccessInfo>* access_infos);

 private:
  bool ConsolidateElementLoad(MapHandles const& maps,
                              ElementAccessInfo* access_info);
  bool LookupSpecialFieldAccessor(Handle<Map> map, Handle<Name> name,
                                  PropertyAccessInfo* access_info);
  bool LookupTransition(Handle<Map> map, Handle<Name> name,
                        MaybeHandle<JSObject> holder,
                        PropertyAccessInfo* access_info);

  CompilationDependencies* dependencies() const { return dependencies_; }
  Factory* factory() const;
  Isolate* isolate() const { return isolate_; }
  Handle<Context> native_context() const { return native_context_; }
  Zone* zone() const { return zone_; }

  CompilationDependencies* const dependencies_;
  Handle<Context> const native_context_;
  Isolate* const isolate_;
  TypeCache const& type_cache_;
  Zone* const zone_;

  DISALLOW_COPY_AND_ASSIGN(AccessInfoFactory);
};

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_ACCESS_INFO_H_
