// Copyright 2012 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_TYPE_INFO_H_
#define V8_TYPE_INFO_H_

#include "src/allocation.h"
#include "src/contexts.h"
#include "src/globals.h"
#include "src/token.h"
#include "src/types.h"
#include "src/zone.h"

namespace v8 {
namespace internal {

// Forward declarations.
class SmallMapList;


class TypeFeedbackOracle: public ZoneObject {
 public:
  TypeFeedbackOracle(Isolate* isolate, Zone* zone, Handle<Code> code,
                     Handle<TypeFeedbackVector> feedback_vector,
                     Handle<Context> native_context);

  InlineCacheState LoadInlineCacheState(TypeFeedbackId id);
  InlineCacheState LoadInlineCacheState(FeedbackVectorSlot slot);
  bool StoreIsUninitialized(TypeFeedbackId id);
  bool StoreIsUninitialized(FeedbackVectorSlot slot);
  bool CallIsUninitialized(FeedbackVectorSlot slot);
  bool CallIsMonomorphic(FeedbackVectorSlot slot);
  bool KeyedArrayCallIsHoley(TypeFeedbackId id);
  bool CallNewIsMonomorphic(FeedbackVectorSlot slot);

  // TODO(1571) We can't use ForInStatement::ForInType as the return value due
  // to various cycles in our headers.
  // TODO(rossberg): once all oracle access is removed from ast.cc, it should
  // be possible.
  byte ForInType(FeedbackVectorSlot feedback_vector_slot);

  void GetStoreModeAndKeyType(TypeFeedbackId id,
                              KeyedAccessStoreMode* store_mode,
                              IcCheckType* key_type);
  void GetStoreModeAndKeyType(FeedbackVectorSlot slot,
                              KeyedAccessStoreMode* store_mode,
                              IcCheckType* key_type);

  void PropertyReceiverTypes(FeedbackVectorSlot slot, Handle<Name> name,
                             SmallMapList* receiver_types);
  void KeyedPropertyReceiverTypes(FeedbackVectorSlot slot,
                                  SmallMapList* receiver_types, bool* is_string,
                                  IcCheckType* key_type);
  void AssignmentReceiverTypes(TypeFeedbackId id, Handle<Name> name,
                               SmallMapList* receiver_types);
  void AssignmentReceiverTypes(FeedbackVectorSlot slot, Handle<Name> name,
                               SmallMapList* receiver_types);
  void KeyedAssignmentReceiverTypes(TypeFeedbackId id,
                                    SmallMapList* receiver_types,
                                    KeyedAccessStoreMode* store_mode,
                                    IcCheckType* key_type);
  void KeyedAssignmentReceiverTypes(FeedbackVectorSlot slot,
                                    SmallMapList* receiver_types,
                                    KeyedAccessStoreMode* store_mode,
                                    IcCheckType* key_type);
  void CountReceiverTypes(TypeFeedbackId id,
                          SmallMapList* receiver_types);
  void CountReceiverTypes(FeedbackVectorSlot slot,
                          SmallMapList* receiver_types);

  void CollectReceiverTypes(FeedbackVectorSlot slot, SmallMapList* types);
  void CollectReceiverTypes(TypeFeedbackId id,
                            SmallMapList* types);
  template <class T>
  void CollectReceiverTypes(T* obj, SmallMapList* types);

  static bool IsRelevantFeedback(Map* map, Context* native_context) {
    Object* constructor = map->GetConstructor();
    return !constructor->IsJSFunction() ||
           JSFunction::cast(constructor)->context()->native_context() ==
               native_context;
  }

  Handle<JSFunction> GetCallTarget(FeedbackVectorSlot slot);
  Handle<AllocationSite> GetCallAllocationSite(FeedbackVectorSlot slot);
  Handle<JSFunction> GetCallNewTarget(FeedbackVectorSlot slot);
  Handle<AllocationSite> GetCallNewAllocationSite(FeedbackVectorSlot slot);

  bool LoadIsBuiltin(TypeFeedbackId id, Builtins::Name builtin_id);

  // TODO(1571) We can't use ToBooleanStub::Types as the return value because
  // of various cycles in our headers. Death to tons of implementations in
  // headers!! :-P
  uint16_t ToBooleanTypes(TypeFeedbackId id);

  // Get type information for arithmetic operations and compares.
  void BinaryType(TypeFeedbackId id,
                  Type** left,
                  Type** right,
                  Type** result,
                  Maybe<int>* fixed_right_arg,
                  Handle<AllocationSite>* allocation_site,
                  Token::Value operation);

  void CompareType(TypeFeedbackId id,
                   Type** left,
                   Type** right,
                   Type** combined);

  Type* CountType(TypeFeedbackId id);

  Zone* zone() const { return zone_; }
  Isolate* isolate() const { return isolate_; }

 private:
  void CollectReceiverTypes(FeedbackVectorSlot slot, Handle<Name> name,
                            Code::Flags flags, SmallMapList* types);
  void CollectReceiverTypes(TypeFeedbackId id, Handle<Name> name,
                            Code::Flags flags, SmallMapList* types);
  template <class T>
  void CollectReceiverTypes(T* obj, Handle<Name> name, Code::Flags flags,
                            SmallMapList* types);

  // Returns true if there is at least one string map and if
  // all maps are string maps.
  bool HasOnlyStringMaps(SmallMapList* receiver_types);

  void SetInfo(TypeFeedbackId id, Object* target);

  void BuildDictionary(Handle<Code> code);
  void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
  void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
  void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
                          Code* old_code,
                          Code* new_code);
  void ProcessRelocInfos(ZoneList<RelocInfo>* infos);

  // Returns an element from the backing store. Returns undefined if
  // there is no information.
  Handle<Object> GetInfo(TypeFeedbackId id);

  // Returns an element from the type feedback vector. Returns undefined
  // if there is no information.
  Handle<Object> GetInfo(FeedbackVectorSlot slot);

 private:
  Handle<Context> native_context_;
  Isolate* isolate_;
  Zone* zone_;
  Handle<UnseededNumberDictionary> dictionary_;
  Handle<TypeFeedbackVector> feedback_vector_;

  DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_TYPE_INFO_H_
