// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_COMPILER_AOT_PRECOMPILER_H_
#define RUNTIME_VM_COMPILER_AOT_PRECOMPILER_H_

#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif  // defined(DART_PRECOMPILED_RUNTIME)

#include "vm/allocation.h"
#include "vm/compiler/aot/dispatch_table_generator.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/hash_map.h"
#include "vm/hash_table.h"
#include "vm/object.h"
#include "vm/symbols.h"
#include "vm/timer.h"

namespace dart {

// Forward declarations.
class Class;
class Error;
class Field;
class Function;
class GrowableObjectArray;
class String;
class Precompiler;
class FlowGraph;
class PrecompilerTracer;
class RetainedReasonsWriter;

class TableSelectorKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef int32_t Key;
  typedef int32_t Value;
  typedef int32_t Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key; }

  static inline bool IsKeyEqual(Pair pair, Key key) { return pair == key; }
};

typedef DirectChainedHashMap<TableSelectorKeyValueTrait> TableSelectorSet;

class SymbolKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const String* Key;
  typedef const String* Value;
  typedef const String* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key->Hash(); }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<SymbolKeyValueTrait> SymbolSet;

// Traits for the HashTable template.
struct FunctionKeyTraits {
  static uint32_t Hash(const Object& key) { return Function::Cast(key).Hash(); }
  static const char* Name() { return "FunctionKeyTraits"; }
  static bool IsMatch(const Object& x, const Object& y) {
    return x.ptr() == y.ptr();
  }
  static bool ReportStats() { return false; }
};

typedef UnorderedHashSet<FunctionKeyTraits> FunctionSet;

class ClassKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const Class* Key;
  typedef const Class* Value;
  typedef const Class* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) {
    return Utils::WordHash(CombineHashes(key->id(), key->token_pos().Hash()));
  }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<ClassKeyValueTrait> ClassSet;

class AbstractTypeKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const AbstractType* Key;
  typedef const AbstractType* Value;
  typedef const AbstractType* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key->Hash(); }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<AbstractTypeKeyValueTrait> AbstractTypeSet;

class FunctionTypeKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const FunctionType* Key;
  typedef const FunctionType* Value;
  typedef const FunctionType* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key->Hash(); }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<FunctionTypeKeyValueTrait> FunctionTypeSet;

class TypeParameterKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const TypeParameter* Key;
  typedef const TypeParameter* Value;
  typedef const TypeParameter* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key->Hash(); }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<TypeParameterKeyValueTrait> TypeParameterSet;

class TypeArgumentsKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const TypeArguments* Key;
  typedef const TypeArguments* Value;
  typedef const TypeArguments* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key->Hash(); }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<TypeArgumentsKeyValueTrait> TypeArgumentsSet;

class ProgramElementKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const Object* Key;
  typedef const Object* Value;
  typedef const Object* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) {
    if (key->IsFunction()) {
      return Function::Cast(*key).Hash();
    } else if (key->IsField()) {
      return Utils::WordHash(Field::Cast(*key).kernel_offset());
    } else if (key->IsClass()) {
      return Utils::WordHash(Class::Cast(*key).kernel_offset());
    } else if (key->IsLibrary()) {
      // This must not use library's index or url hash because both
      // of these might change during precompilation: urls are changed
      // by |Precompiler::Obfuscate| and library index is changed by
      // |Precompiler::DropLibraries|.
      return Utils::WordHash(Library::Cast(*key).KernelLibraryOffset());
    }
    FATAL("Unexpected type: %s\n", key->ToCString());
  }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<ProgramElementKeyValueTrait> ProgramElementSet;

class InstanceKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef const Instance* Key;
  typedef const Instance* Value;
  typedef const Instance* Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) { return key->CanonicalizeHash(); }

  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair->ptr() == key->ptr();
  }
};

typedef DirectChainedHashMap<InstanceKeyValueTrait> InstanceSet;

class Precompiler : public ValueObject {
 public:
  static ErrorPtr CompileAll();

  static void CompileFunction(Precompiler* precompiler,
                              Thread* thread,
                              const Function& function);

  // Returns true if get:runtimeType is not overloaded by any class.
  bool get_runtime_type_is_unique() const {
    return get_runtime_type_is_unique_;
  }

  compiler::ObjectPoolBuilder* global_object_pool_builder() {
    return &global_object_pool_builder_;
  }

  compiler::SelectorMap* selector_map() {
    return dispatch_table_generator_->selector_map();
  }

  static Precompiler* Instance() { return singleton_; }

  void AddField(const Field& field);
  void AddTableSelector(const compiler::TableSelector* selector);

  enum class Phase {
    kPreparation,
    kCompilingConstructorsForInstructionCounts,
    kFixpointCodeGeneration,
    kDone,
  };

  Phase phase() const { return phase_; }

  bool is_tracing() const { return is_tracing_; }

  Thread* thread() const { return thread_; }
  Zone* zone() const { return zone_; }

 private:
  static Precompiler* singleton_;

  // Scope which activates machine readable precompiler tracing if tracer
  // is available.
  class TracingScope : public ValueObject {
   public:
    explicit TracingScope(Precompiler* precompiler)
        : precompiler_(precompiler), was_tracing_(precompiler->is_tracing_) {
      precompiler->is_tracing_ = (precompiler->tracer_ != nullptr);
    }

    ~TracingScope() { precompiler_->is_tracing_ = was_tracing_; }

   private:
    Precompiler* const precompiler_;
    const bool was_tracing_;
  };

  explicit Precompiler(Thread* thread);
  ~Precompiler();

  void ReportStats();

  void DoCompileAll();
  void AddRoots();
  void AddAnnotatedRoots();
  void Iterate();

  void AddRetainReason(const Object& obj, const char* reason);
  void AddType(const AbstractType& type);
  void AddTypesOf(const Class& cls);
  void AddTypesOf(const Function& function);
  void AddTypeParameters(const TypeParameters& params);
  void AddTypeArguments(const TypeArguments& args);
  void AddCalleesOf(const Function& function, intptr_t gop_offset);
  void AddCalleesOfHelper(const Object& entry,
                          String* temp_selector,
                          Class* temp_cls);
  void AddConstObject(const class Instance& instance);
  void AddClosureCall(const String& selector,
                      const Array& arguments_descriptor);
  void AddFunction(const Function& function, const char* retain_reason);
  void AddInstantiatedClass(const Class& cls);
  void AddSelector(const String& selector);
  bool IsSent(const String& selector);
  bool IsHitByTableSelector(const Function& function);
  // Returns the reason if the function must be retained, otherwise nullptr.
  const char* MustRetainFunction(const Function& function);
  void AddApiUse(const Object& obj);
  bool HasApiUse(const Object& obj);

  void ProcessFunction(const Function& function);
  void CheckForNewDynamicFunctions();
  void CollectCallbackFields();

  void AttachOptimizedTypeTestingStub();

  void TraceForRetainedFunctions();
  void FinalizeDispatchTable();
  void ReplaceFunctionStaticCallEntries();
  void DropFunctions();
  void DropFields();
  void VisitConstantInstance(ObjectPtr instance,
                             WeakTable* visited,
                             ObjectStore* object_store);
  void DropTransitiveUserDefinedConstants();
  void TraceTypesFromRetainedClasses();
  void DropMetadata();
  void DropLibraryEntries();
  void DropClasses();
  void DropLibraries();
  void DiscardCodeObjects();
  void PruneDictionaries();

  DEBUG_ONLY(FunctionPtr FindUnvisitedRetainedFunction());

  void Obfuscate();

  void CollectDynamicFunctionNames();

  void PrecompileStaticInitializers();
  void PrecompileConstructors();

  void FinalizeAllClasses();

  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }

  Thread* thread_;
  Zone* zone_;

  bool changed_;
  bool retain_root_library_caches_;
  intptr_t function_count_;
  intptr_t class_count_;
  intptr_t selector_count_;
  intptr_t dropped_function_count_;
  intptr_t dropped_field_count_;
  intptr_t dropped_class_count_;
  intptr_t dropped_typearg_count_;
  intptr_t dropped_type_count_;
  intptr_t dropped_functiontype_count_;
  intptr_t dropped_typeparam_count_;
  intptr_t dropped_library_count_;
  intptr_t dropped_constants_arrays_entries_count_;

  compiler::ObjectPoolBuilder global_object_pool_builder_;
  GrowableObjectArray& libraries_;
  const GrowableObjectArray& pending_functions_;
  SymbolSet sent_selectors_;
  FunctionSet functions_called_dynamically_;
  FunctionSet functions_with_entry_point_pragmas_;
  FunctionSet seen_functions_;
  FunctionSet possibly_retained_functions_;
  FieldSet fields_to_retain_;
  FunctionSet functions_to_retain_;
  ClassSet classes_to_retain_;
  TypeArgumentsSet typeargs_to_retain_;
  AbstractTypeSet types_to_retain_;
  FunctionTypeSet functiontypes_to_retain_;
  TypeParameterSet typeparams_to_retain_;
  InstanceSet consts_to_retain_;
  TableSelectorSet seen_table_selectors_;
  ProgramElementSet api_uses_;
  Error& error_;

  compiler::DispatchTableGenerator* dispatch_table_generator_;

  bool get_runtime_type_is_unique_;

  Phase phase_ = Phase::kPreparation;
  PrecompilerTracer* tracer_ = nullptr;
  RetainedReasonsWriter* retained_reasons_writer_ = nullptr;
  bool is_tracing_ = false;
};

class FunctionsTraits {
 public:
  static const char* Name() { return "FunctionsTraits"; }
  static bool ReportStats() { return false; }

  static bool IsMatch(const Object& a, const Object& b) {
    return String::Cast(a).ptr() == String::Cast(b).ptr();
  }
  static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); }
};

typedef UnorderedHashMap<FunctionsTraits> UniqueFunctionsMap;

#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
// ObfuscationMap maps Strings to Strings.
class ObfuscationMapTraits {
 public:
  static const char* Name() { return "ObfuscationMapTraits"; }
  static bool ReportStats() { return false; }

  // Only for non-descriptor lookup and table expansion.
  static bool IsMatch(const Object& a, const Object& b) {
    return a.ptr() == b.ptr();
  }

  static uword Hash(const Object& key) { return String::Cast(key).Hash(); }
};
typedef UnorderedHashMap<ObfuscationMapTraits> ObfuscationMap;

// Obfuscator is a helper class that is responsible for obfuscating
// identifiers when obfuscation is enabled via isolate flags.
//
class Obfuscator : public ValueObject {
 public:
  // Create Obfuscator for the given |thread|, with the given |private_key|.
  // This private key will be used when obfuscating private identifiers
  // (those starting with '_').
  //
  // If obfuscation is enabled constructor will restore obfuscation state
  // from ObjectStore::obfuscation_map()
  //
  // Note: only a single instance of obfuscator should exist at any given
  // moment on the stack because Obfuscator takes ownership of obfuscation
  // map. ObjectStore::obfuscation_map() will only be updated when
  // this Obfuscator is destroyed.
  Obfuscator(Thread* thread, const String& private_key);

  // If obfuscation is enabled - commit accumulated renames to ObjectStore.
  ~Obfuscator();

  // If obfuscation is enabled return a rename for the given |name|,
  // otherwise it is a no-op.
  //
  // Note: |name| *must* be a Symbol.
  //
  // By default renames are aware about mangling scheme used for private names:
  // '_ident@key' and '_ident' will be renamed consistently. If such
  // interpretation is undesirable e.g. it is known that name does not
  // contain a private key suffix or name is not a Dart identifier at all
  // then this function should be called with |atomic| set to true.
  //
  // Note: if obfuscator was created with private_key then all
  // renames *must* be atomic.
  //
  // This method is guaranteed to return the same value for the same
  // input and it always preserves leading '_' even for atomic renames.
  StringPtr Rename(const String& name, bool atomic = false) {
    if (state_ == nullptr) {
      return name.ptr();
    }

    return state_->RenameImpl(name, atomic);
  }

  // Given a sequence of obfuscated identifiers deobfuscate it.
  //
  // This method is only used by parser when resolving conditional imports
  // because it needs deobfuscated names to lookup in the environment.
  //
  // Note: this operation is not optimized because is very infrequent.
  static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces);

  // Serialize renaming map as a mallocated array of strings.
  static const char** SerializeMap(Thread* thread);

  void PreventRenaming(const char* name);
  void PreventRenaming(const String& name) { state_->PreventRenaming(name); }

 private:
  // Populate renaming map with names that should have identity renaming.
  // (or in other words: with those names that should not be renamed).
  void InitializeRenamingMap();

  // ObjectStore::obfuscation_map() is an Array with two elements:
  // first element is the last used rename and the second element is
  // renaming map.
  static constexpr intptr_t kSavedStateNameIndex = 0;
  static constexpr intptr_t kSavedStateRenamesIndex = 1;
  static constexpr intptr_t kSavedStateSize = 2;

  static ArrayPtr GetRenamesFromSavedState(const Array& saved_state) {
    Array& renames = Array::Handle();
    renames ^= saved_state.At(kSavedStateRenamesIndex);
    return renames.ptr();
  }

  static StringPtr GetNameFromSavedState(const Array& saved_state) {
    String& name = String::Handle();
    name ^= saved_state.At(kSavedStateNameIndex);
    return name.ptr();
  }

  class ObfuscationState : public ZoneAllocated {
   public:
    ObfuscationState(Thread* thread,
                     const Array& saved_state,
                     const String& private_key)
        : thread_(thread),
          saved_state_(saved_state),
          renames_(GetRenamesFromSavedState(saved_state)),
          private_key_(private_key),
          string_(String::Handle(thread->zone())),
          renamed_(String::Handle(thread->zone())) {
      memset(name_, 0, sizeof(name_));

      // Restore last used rename.
      string_ = GetNameFromSavedState(saved_state);
      if (!string_.IsNull()) {
        string_.ToUTF8(reinterpret_cast<uint8_t*>(name_), sizeof(name_));
      }
    }

    void SaveState();

    // Return a rename for the given |name|.
    //
    // Note: |name| *must* be a Symbol.
    //
    // By default renames are aware about mangling scheme used for private
    // names, getters and setters: '_ident@key', 'get:_ident@key' and
    // '_ident' will be renamed consistently. If such interpretation is
    // undesirable e.g. it is known that name does not contain a private
    // key suffix or name is not a Dart identifier at all
    // then this function should be called with |atomic| set to true.
    //
    // Note: if obfuscator was created with private_key then all
    // renames *must* be atomic.
    //
    // This method is guaranteed to return the same value for the same
    // input.
    StringPtr RenameImpl(const String& name, bool atomic);

    // Register an identity (name -> name) mapping in the renaming map.
    //
    // This essentially prevents the given name from being renamed.
    void PreventRenaming(const String& name);
    void PreventRenaming(const char* name);

   private:
    // Build rename for the given |name|.
    //
    // For atomic renames BuildRename just returns the next
    // available rename generated by AtomicRename(...).
    //
    // For non-atomic renames BuildRename ensures that private mangled
    // identifiers (_ident@key) are renamed consistently with non-mangled
    // counterparts (_ident).
    StringPtr BuildRename(const String& name, bool atomic);

    // Generate a new rename. If |should_be_private| is set to true
    // then we prefix returned identifier with '_'.
    StringPtr NewAtomicRename(bool should_be_private);

    // Update next_ to generate the next free rename.
    void NextName();

    Thread* thread_;

    // Saved obfuscation state (ObjectStore::obfuscation_map())
    const Array& saved_state_;

    // Last used rename. Renames are only using a-zA-Z characters
    // and are generated in order: a, b, ..., z, A, ..., Z, aa, ba, ...
    char name_[100];

    ObfuscationMap renames_;

    const String& private_key_;

    // Temporary handles.
    String& string_;
    String& renamed_;
  };

  // Current obfuscation state or nullptr if obfuscation is not enabled.
  ObfuscationState* state_;
};
#else
// Minimal do-nothing implementation of an Obfuscator for non-precompiler
// builds.
class Obfuscator {
 public:
  Obfuscator(Thread* thread, const String& private_key) {}
  ~Obfuscator() {}

  StringPtr Rename(const String& name, bool atomic = false) {
    return name.ptr();
  }

  void PreventRenaming(const String& name) {}

  static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces) {}
};
#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)

}  // namespace dart

#endif  // RUNTIME_VM_COMPILER_AOT_PRECOMPILER_H_
