// Copyright (c) 2016, 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_KERNEL_LOADER_H_
#define RUNTIME_VM_KERNEL_LOADER_H_

#if !defined(DART_PRECOMPILED_RUNTIME)

#include "vm/bit_vector.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/hash_map.h"
#include "vm/kernel.h"
#include "vm/object.h"
#include "vm/symbols.h"

namespace dart {
namespace kernel {

class KernelLoader;

class BuildingTranslationHelper : public TranslationHelper {
 public:
  BuildingTranslationHelper(KernelLoader* loader,
                            Thread* thread,
                            Heap::Space space)
      : TranslationHelper(thread, space),
        loader_(loader),
        library_lookup_handle_(Library::Handle(thread->zone())) {}
  virtual ~BuildingTranslationHelper() {}

  virtual RawLibrary* LookupLibraryByKernelLibrary(NameIndex library);
  virtual RawClass* LookupClassByKernelClass(NameIndex klass);

 private:
  KernelLoader* loader_;

#if defined(DEBUG)
  class LibraryLookupHandleScope {
   public:
    explicit LibraryLookupHandleScope(Library& lib) : lib_(lib) {
      ASSERT(lib_.IsNull());
    }

    ~LibraryLookupHandleScope() { lib_ = Library::null(); }

   private:
    Library& lib_;

    DISALLOW_COPY_AND_ASSIGN(LibraryLookupHandleScope);
  };
#endif  // defined(DEBUG)

  // Preallocated handle for use in LookupClassByKernelClass().
  Library& library_lookup_handle_;

  DISALLOW_COPY_AND_ASSIGN(BuildingTranslationHelper);
};

template <typename VmType>
class Mapping {
 public:
  bool Lookup(intptr_t canonical_name, VmType** handle) {
    typename MapType::Pair* pair = map_.LookupPair(canonical_name);
    if (pair != NULL) {
      *handle = pair->value;
      return true;
    }
    return false;
  }

  void Insert(intptr_t canonical_name, VmType* object) {
    map_.Insert(canonical_name, object);
  }

 private:
  typedef IntMap<VmType*> MapType;
  MapType map_;
};

class LibraryIndex {
 public:
  // |kernel_data| is the kernel data for one library alone.
  // binary_version can be -1 in which case some parts of the index might not
  // be read.
  explicit LibraryIndex(const ExternalTypedData& kernel_data,
                        int32_t binary_version);

  intptr_t class_count() const { return class_count_; }
  intptr_t procedure_count() const { return procedure_count_; }

  intptr_t ClassOffset(intptr_t index) const {
    return reader_.ReadUInt32At(class_index_offset_ + index * 4);
  }

  intptr_t ProcedureOffset(intptr_t index) const {
    return reader_.ReadUInt32At(procedure_index_offset_ + index * 4);
  }

  intptr_t SizeOfClassAtOffset(intptr_t class_offset) const {
    for (intptr_t i = 0, offset = class_index_offset_; i < class_count_;
         ++i, offset += 4) {
      if (static_cast<intptr_t>(reader_.ReadUInt32At(offset)) == class_offset) {
        return reader_.ReadUInt32At(offset + 4) - class_offset;
      }
    }
    UNREACHABLE();
    return -1;
  }

  bool HasSourceReferences() {
    if (binary_version_ < 25) return false;
    return true;
  }

  intptr_t SourceReferencesOffset() { return source_references_offset_; }

 private:
  Reader reader_;
  int32_t binary_version_;
  intptr_t source_references_offset_;
  intptr_t class_index_offset_;
  intptr_t class_count_;
  intptr_t procedure_index_offset_;
  intptr_t procedure_count_;

  DISALLOW_COPY_AND_ASSIGN(LibraryIndex);
};

class ClassIndex {
 public:
  // |class_offset| is the offset of class' kernel data in |buffer| of
  // size |size|. The size of the class' kernel data is |class_size|.
  ClassIndex(const uint8_t* buffer,
             intptr_t buffer_size,
             intptr_t class_offset,
             intptr_t class_size);

  // |class_offset| is the offset of class' kernel data in |kernel_data|.
  // The size of the class' kernel data is |class_size|.
  ClassIndex(const ExternalTypedData& kernel_data,
             intptr_t class_offset,
             intptr_t class_size);

  intptr_t procedure_count() const { return procedure_count_; }

  intptr_t ProcedureOffset(intptr_t index) const {
    return reader_.ReadUInt32At(procedure_index_offset_ + index * 4);
  }

 private:
  void Init(intptr_t class_offset, intptr_t class_size);

  Reader reader_;
  intptr_t procedure_count_;
  intptr_t procedure_index_offset_;

  DISALLOW_COPY_AND_ASSIGN(ClassIndex);
};

struct UriToSourceTableEntry : public ZoneAllocated {
  UriToSourceTableEntry() {}

  const String* uri = nullptr;
  const String* sources = nullptr;
  const TypedData* line_starts = nullptr;
};

struct UriToSourceTableTrait {
  typedef UriToSourceTableEntry* Value;
  typedef const UriToSourceTableEntry* Key;
  typedef UriToSourceTableEntry* Pair;

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

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

  static inline intptr_t Hashcode(Key key) { return key->uri->Hash(); }

  static inline bool IsKeyEqual(Pair kv, Key key) {
    // Only compare uri.
    return kv->uri->CompareTo(*key->uri) == 0;
  }
};

class KernelLoader : public ValueObject {
 public:
  explicit KernelLoader(
      Program* program,
      DirectChainedHashMap<UriToSourceTableTrait>* uri_to_source_table);
  static Object& LoadEntireProgram(Program* program,
                                   bool process_pending_classes = true);

  // Returns the library containing the main procedure, null if there
  // was no main procedure, or a failure object if there was an error.
  RawObject* LoadProgram(bool process_pending_classes = true);

  // Returns the function which will evaluate the expression, or a failure
  // object if there was an error.
  RawObject* LoadExpressionEvaluationFunction(const String& library_url,
                                              const String& klass);

  // Finds all libraries that have been modified in this incremental
  // version of the kernel program file.
  //
  // When [force_reload] is false and if [p_num_classes], [p_num_procedures] are
  // not nullptr, then they are populated with number of classes and top-level
  // procedures in [program].
  static void FindModifiedLibraries(Program* program,
                                    Isolate* isolate,
                                    BitVector* modified_libs,
                                    bool force_reload,
                                    bool* is_empty_program,
                                    intptr_t* p_num_classes,
                                    intptr_t* p_num_procedures);

  static RawString* FindSourceForScript(const uint8_t* kernel_buffer,
                                        intptr_t kernel_buffer_length,
                                        const String& url);

  RawLibrary* LoadLibrary(intptr_t index);

  void FinishTopLevelClassLoading(const Class& toplevel_class,
                                  const Library& library,
                                  const LibraryIndex& library_index);

  static void FinishLoading(const Class& klass);

  void ReadObfuscationProhibitions();

  const Array& ReadConstantTable();

  // Check for the presence of a (possibly const) constructor for the
  // 'ExternalName' class. If found, returns the name parameter to the
  // constructor.
  RawString* DetectExternalNameCtor();

  // Check for the presence of a (possibly const) constructor for the 'pragma'
  // class. Returns whether it was found (no details about the type of pragma).
  bool DetectPragmaCtor();

  bool IsClassName(NameIndex name, const String& library, const String& klass);

  void AnnotateNativeProcedures(const Array& constant_table);
  void LoadNativeExtensionLibraries(const Array& constant_table);
  void EvaluateDelayedPragmas();

  void ReadVMAnnotations(intptr_t annotation_count,
                         String* native_name,
                         bool* is_potential_native,
                         bool* has_pragma_annotation);

  const String& DartSymbolPlain(StringIndex index) {
    return translation_helper_.DartSymbolPlain(index);
  }
  const String& DartSymbolObfuscate(StringIndex index) {
    return translation_helper_.DartSymbolObfuscate(index);
  }

  const String& LibraryUri(intptr_t library_index) {
    return translation_helper_.DartSymbolPlain(
        translation_helper_.CanonicalNameString(
            library_canonical_name(library_index)));
  }

  intptr_t library_offset(intptr_t index) {
    kernel::Reader reader(program_->kernel_data(),
                          program_->kernel_data_size());
    return reader.ReadFromIndexNoReset(reader.size(),
                                       LibraryCountFieldCountFromEnd + 1,
                                       program_->library_count() + 1, index);
  }

  NameIndex library_canonical_name(intptr_t index) {
    kernel::Reader reader(program_->kernel_data(),
                          program_->kernel_data_size());
    reader.set_offset(library_offset(index));

    // Start reading library.
    reader.ReadFlags();
    return reader.ReadCanonicalNameReference();
  }

  uint8_t CharacterAt(StringIndex string_index, intptr_t index);

 private:
  friend class BuildingTranslationHelper;

  KernelLoader(const Script& script,
               const ExternalTypedData& kernel_data,
               intptr_t data_program_offset);

  void InitializeFields(
      DirectChainedHashMap<UriToSourceTableTrait>* uri_to_source_table);
  static void index_programs(kernel::Reader* reader,
                             GrowableArray<intptr_t>* subprogram_file_starts);
  void walk_incremental_kernel(BitVector* modified_libs,
                               bool* is_empty_program,
                               intptr_t* p_num_classes,
                               intptr_t* p_num_procedures);

  void LoadPreliminaryClass(ClassHelper* class_helper,
                            intptr_t type_parameter_count);

  void ReadInferredType(const Field& field, intptr_t kernel_offset);
  void CheckForInitializer(const Field& field);

  void LoadClass(const Library& library,
                 const Class& toplevel_class,
                 intptr_t class_end,
                 Class* out_class);

  void FinishClassLoading(const Class& klass,
                          const Library& library,
                          const Class& toplevel_class,
                          intptr_t class_offset,
                          const ClassIndex& class_index,
                          ClassHelper* class_helper);

  void LoadProcedure(const Library& library,
                     const Class& owner,
                     bool in_class,
                     intptr_t procedure_end);

  RawArray* MakeFieldsArray();
  RawArray* MakeFunctionsArray();

  RawScript* LoadScriptAt(
      intptr_t index,
      DirectChainedHashMap<UriToSourceTableTrait>* uri_to_source_table);

  // If klass's script is not the script at the uri index, return a PatchClass
  // for klass whose script corresponds to the uri index.
  // Otherwise return klass.
  const Object& ClassForScriptAt(const Class& klass, intptr_t source_uri_index);
  RawScript* ScriptAt(intptr_t source_uri_index) {
    return kernel_program_info_.ScriptAt(source_uri_index);
  }

  void GenerateFieldAccessors(const Class& klass,
                              const Field& field,
                              FieldHelper* field_helper);

  void LoadLibraryImportsAndExports(Library* library,
                                    const Class& toplevel_class);

  RawLibrary* LookupLibraryOrNull(NameIndex library);
  RawLibrary* LookupLibrary(NameIndex library);
  RawLibrary* LookupLibraryFromClass(NameIndex klass);
  RawClass* LookupClass(const Library& library, NameIndex klass);

  RawFunction::Kind GetFunctionType(ProcedureHelper::Kind procedure_kind);

  void EnsureExternalClassIsLookedUp() {
    if (external_name_class_.IsNull()) {
      ASSERT(external_name_field_.IsNull());
      const Library& internal_lib =
          Library::Handle(zone_, dart::Library::InternalLibrary());
      external_name_class_ = internal_lib.LookupClass(Symbols::ExternalName());
      external_name_field_ = external_name_class_.LookupField(Symbols::name());
    } else {
      ASSERT(!external_name_field_.IsNull());
    }
  }

  void EnsurePragmaClassIsLookedUp() {
    if (pragma_class_.IsNull()) {
      const Library& core_lib =
          Library::Handle(zone_, dart::Library::CoreLibrary());
      pragma_class_ = core_lib.LookupLocalClass(Symbols::Pragma());
      ASSERT(!pragma_class_.IsNull());
    }
  }

  void EnsurePotentialNatives() {
    potential_natives_ = kernel_program_info_.potential_natives();
    if (potential_natives_.IsNull()) {
      // To avoid too many grows in this array, we'll set it's initial size to
      // something close to the actual number of potential native functions.
      potential_natives_ = GrowableObjectArray::New(100, Heap::kNew);
      kernel_program_info_.set_potential_natives(potential_natives_);
    }
  }

  void EnsurePotentialPragmaFunctions() {
    potential_pragma_functions_ =
        translation_helper_.EnsurePotentialPragmaFunctions();
  }

  void EnsurePotentialExtensionLibraries() {
    if (potential_extension_libraries_.IsNull()) {
      potential_extension_libraries_ = GrowableObjectArray::New();
    }
  }

  Program* program_;

  Thread* thread_;
  Zone* zone_;
  Isolate* isolate_;
  Array& patch_classes_;
  ActiveClass active_class_;
  // This is the offset of the current library within
  // the whole kernel program.
  intptr_t library_kernel_offset_;
  // This is the offset by which offsets, which are set relative
  // to their library's kernel data, have to be corrected.
  intptr_t correction_offset_;
  bool loading_native_wrappers_library_;

  NameIndex skip_vmservice_library_;

  ExternalTypedData& library_kernel_data_;
  KernelProgramInfo& kernel_program_info_;
  BuildingTranslationHelper translation_helper_;
  KernelReaderHelper helper_;
  TypeTranslator type_translator_;
  InferredTypeMetadataHelper inferred_type_metadata_helper_;
  BytecodeMetadataHelper bytecode_metadata_helper_;

  Class& external_name_class_;
  Field& external_name_field_;
  GrowableObjectArray& potential_natives_;
  GrowableObjectArray& potential_pragma_functions_;
  GrowableObjectArray& potential_extension_libraries_;

  Class& pragma_class_;

  Smi& name_index_handle_;

  // We "re-use" the normal .dill file format for encoding compiled evaluation
  // expressions from the debugger.  This allows us to also reuse the normal
  // a) kernel loader b) flow graph building code.  The encoding is either one
  // of the following two options:
  //
  //   * Option a) The expression is evaluated inside an instance method call
  //               context:
  //
  //   Program:
  //   |> library "evaluate:source"
  //      |> class "#DebugClass"
  //         |> procedure ":Eval"
  //
  //   * Option b) The expression is evaluated outside an instance method call
  //               context:
  //
  //   Program:
  //   |> library "evaluate:source"
  //      |> procedure ":Eval"
  //
  // See
  //   * pkg/front_end/lib/src/fasta/incremental_compiler.dart:compileExpression
  //   * pkg/front_end/lib/src/fasta/kernel/utils.dart:serializeProcedure
  //
  Library& expression_evaluation_library_;
  Function& expression_evaluation_function_;

  GrowableArray<const Function*> functions_;
  GrowableArray<const Field*> fields_;

  DISALLOW_COPY_AND_ASSIGN(KernelLoader);
};

RawFunction* CreateFieldInitializerFunction(Thread* thread,
                                            Zone* zone,
                                            const Field& field);

ParsedFunction* ParseStaticFieldInitializer(Zone* zone, const Field& field);

}  // namespace kernel
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
#endif  // RUNTIME_VM_KERNEL_LOADER_H_
