// 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/codegen/machine-type.h"
#include "src/compiler/types.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/field-index.h"
#include "src/objects/map.h"
#include "src/objects/objects.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {

// Forward declarations.
class Factory;

namespace compiler {

// Forward declarations.
class CompilationDependencies;
class CompilationDependency;
class ElementAccessFeedback;
class JSHeapBroker;
class TypeCache;

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

// This class encapsulates all information required to access a certain element.
class ElementAccessInfo final {
 public:
  ElementAccessInfo(ZoneVector<Handle<Map>>&& receiver_maps,
                    ElementsKind elements_kind, Zone* zone);

  ElementsKind elements_kind() const { return elements_kind_; }
  ZoneVector<Handle<Map>> const& receiver_maps() const {
    return receiver_maps_;
  }
  ZoneVector<Handle<Map>> const& transition_sources() const {
    return transition_sources_;
  }

  void AddTransitionSource(Handle<Map> map) {
    CHECK_EQ(receiver_maps_.size(), 1);
    transition_sources_.push_back(map);
  }

 private:
  ElementsKind elements_kind_;
  ZoneVector<Handle<Map>> receiver_maps_;
  ZoneVector<Handle<Map>> transition_sources_;
};

// 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,
    kDataField,
    kDataConstant,
    kAccessorConstant,
    kModuleExport,
    kStringLength
  };

  static PropertyAccessInfo NotFound(Zone* zone, Handle<Map> receiver_map,
                                     MaybeHandle<JSObject> holder);
  static PropertyAccessInfo DataField(
      Zone* zone, Handle<Map> receiver_map,
      ZoneVector<CompilationDependency const*>&& unrecorded_dependencies,
      FieldIndex field_index, Representation field_representation,
      Type field_type, MaybeHandle<Map> field_map = MaybeHandle<Map>(),
      MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
      MaybeHandle<Map> transition_map = MaybeHandle<Map>());
  static PropertyAccessInfo DataConstant(
      Zone* zone, Handle<Map> receiver_map,
      ZoneVector<CompilationDependency const*>&& unrecorded_dependencies,
      FieldIndex field_index, Representation field_representation,
      Type field_type, MaybeHandle<Map> field_map, MaybeHandle<JSObject> holder,
      MaybeHandle<Map> transition_map = MaybeHandle<Map>());
  static PropertyAccessInfo AccessorConstant(Zone* zone,
                                             Handle<Map> receiver_map,
                                             Handle<Object> constant,
                                             MaybeHandle<JSObject> holder);
  static PropertyAccessInfo ModuleExport(Zone* zone, Handle<Map> receiver_map,
                                         Handle<Cell> cell);
  static PropertyAccessInfo StringLength(Zone* zone, Handle<Map> receiver_map);
  static PropertyAccessInfo Invalid(Zone* zone);

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

  void RecordDependencies(CompilationDependencies* dependencies);

  bool IsInvalid() const { return kind() == kInvalid; }
  bool IsNotFound() const { return kind() == kNotFound; }
  bool IsDataField() const { return kind() == kDataField; }
  bool IsDataConstant() const { return kind() == kDataConstant; }
  bool IsAccessorConstant() const { return kind() == kAccessorConstant; }
  bool IsModuleExport() const { return kind() == kModuleExport; }
  bool IsStringLength() const { return kind() == kStringLength; }

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

  Kind kind() const { return kind_; }
  MaybeHandle<JSObject> holder() const {
    // TODO(neis): There was a CHECK here that tries to protect against
    // using the access info without recording its dependencies first.
    // Find a more suitable place for it.
    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_; }
  Representation field_representation() const { return field_representation_; }
  MaybeHandle<Map> field_map() const { return field_map_; }
  ZoneVector<Handle<Map>> const& receiver_maps() const {
    return receiver_maps_;
  }

 private:
  explicit PropertyAccessInfo(Zone* zone);
  PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder,
                     ZoneVector<Handle<Map>>&& receiver_maps);
  PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder,
                     Handle<Object> constant,
                     ZoneVector<Handle<Map>>&& receiver_maps);
  PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder,
                     MaybeHandle<Map> transition_map, FieldIndex field_index,
                     Representation field_representation, Type field_type,
                     MaybeHandle<Map> field_map,
                     ZoneVector<Handle<Map>>&& receiver_maps,
                     ZoneVector<CompilationDependency const*>&& dependencies);

  Kind kind_;
  ZoneVector<Handle<Map>> receiver_maps_;
  ZoneVector<CompilationDependency const*> unrecorded_dependencies_;
  Handle<Object> constant_;
  MaybeHandle<Map> transition_map_;
  MaybeHandle<JSObject> holder_;
  FieldIndex field_index_;
  Representation field_representation_;
  Type field_type_;
  MaybeHandle<Map> field_map_;
};


// Factory class for {ElementAccessInfo}s and {PropertyAccessInfo}s.
class AccessInfoFactory final {
 public:
  AccessInfoFactory(JSHeapBroker* broker, CompilationDependencies* dependencies,
                    Zone* zone);

  base::Optional<ElementAccessInfo> ComputeElementAccessInfo(
      Handle<Map> map, AccessMode access_mode) const;
  bool ComputeElementAccessInfos(
      ElementAccessFeedback const& processed, AccessMode access_mode,
      ZoneVector<ElementAccessInfo>* access_infos) const;

  PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map,
                                               Handle<Name> name,
                                               AccessMode access_mode) const;

  // Convenience wrapper around {ComputePropertyAccessInfo} for multiple maps.
  void ComputePropertyAccessInfos(
      MapHandles const& maps, Handle<Name> name, AccessMode access_mode,
      ZoneVector<PropertyAccessInfo>* access_infos) const;

  // Merge as many of the given {infos} as possible and record any dependencies.
  // Return false iff any of them was invalid, in which case no dependencies are
  // recorded.
  // TODO(neis): Make access_mode part of access info?
  bool FinalizePropertyAccessInfos(
      ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode,
      ZoneVector<PropertyAccessInfo>* result) const;

  // Merge the given {infos} to a single one and record any dependencies. If the
  // merge is not possible, the result has kind {kInvalid} and no dependencies
  // are recorded.
  PropertyAccessInfo FinalizePropertyAccessInfosAsOne(
      ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode) const;

 private:
  base::Optional<ElementAccessInfo> ConsolidateElementLoad(
      ElementAccessFeedback const& processed) const;
  PropertyAccessInfo LookupSpecialFieldAccessor(Handle<Map> map,
                                                Handle<Name> name) const;
  PropertyAccessInfo LookupTransition(Handle<Map> map, Handle<Name> name,
                                      MaybeHandle<JSObject> holder) const;
  PropertyAccessInfo ComputeDataFieldAccessInfo(Handle<Map> receiver_map,
                                                Handle<Map> map,
                                                MaybeHandle<JSObject> holder,
                                                int descriptor,
                                                AccessMode access_mode) const;
  PropertyAccessInfo ComputeAccessorDescriptorAccessInfo(
      Handle<Map> receiver_map, Handle<Name> name, Handle<Map> map,
      MaybeHandle<JSObject> holder, int descriptor,
      AccessMode access_mode) const;

  void MergePropertyAccessInfos(ZoneVector<PropertyAccessInfo> infos,
                                AccessMode access_mode,
                                ZoneVector<PropertyAccessInfo>* result) const;

  CompilationDependencies* dependencies() const { return dependencies_; }
  JSHeapBroker* broker() const { return broker_; }
  Isolate* isolate() const;
  Zone* zone() const { return zone_; }

  JSHeapBroker* const broker_;
  CompilationDependencies* const dependencies_;
  TypeCache const* const type_cache_;
  Zone* const zone_;

  DISALLOW_COPY_AND_ASSIGN(AccessInfoFactory);
};

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

#endif  // V8_COMPILER_ACCESS_INFO_H_
