// Copyright 2016 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.

#include "src/parsing/parse-info.h"

#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h"
#include "src/common/globals.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/heap/heap-inl.h"
#include "src/logging/counters.h"
#include "src/logging/log.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/scope-info.h"
#include "src/zone/zone.h"

namespace v8 {
namespace internal {

UnoptimizedCompileFlags::UnoptimizedCompileFlags(Isolate* isolate,
                                                 int script_id)
    : flags_(0),
      script_id_(script_id),
      function_kind_(FunctionKind::kNormalFunction),
      function_syntax_kind_(FunctionSyntaxKind::kDeclaration) {
  set_collect_type_profile(isolate->is_collecting_type_profile());
  set_coverage_enabled(!isolate->is_best_effort_code_coverage());
  set_block_coverage_enabled(isolate->is_block_code_coverage());
  set_might_always_opt(FLAG_always_opt || FLAG_prepare_always_opt);
  set_allow_natives_syntax(FLAG_allow_natives_syntax);
  set_allow_lazy_compile(FLAG_lazy);
  set_allow_harmony_private_methods(FLAG_harmony_private_methods);
  set_collect_source_positions(!FLAG_enable_lazy_source_positions ||
                               isolate->NeedsDetailedOptimizedCodeLineInfo());
  set_allow_harmony_top_level_await(FLAG_harmony_top_level_await);
  set_allow_harmony_logical_assignment(FLAG_harmony_logical_assignment);
}

// static
UnoptimizedCompileFlags UnoptimizedCompileFlags::ForFunctionCompile(
    Isolate* isolate, SharedFunctionInfo shared) {
  Script script = Script::cast(shared.script());

  UnoptimizedCompileFlags flags(isolate, script.id());

  flags.SetFlagsFromFunction(&shared);
  flags.SetFlagsForFunctionFromScript(script);

  flags.set_allow_lazy_parsing(true);
  flags.set_is_asm_wasm_broken(shared.is_asm_wasm_broken());
  flags.set_is_repl_mode(shared.is_repl_mode());

  // CollectTypeProfile uses its own feedback slots. If we have existing
  // FeedbackMetadata, we can only collect type profile if the feedback vector
  // has the appropriate slots.
  flags.set_collect_type_profile(
      isolate->is_collecting_type_profile() &&
      (shared.HasFeedbackMetadata()
           ? shared.feedback_metadata().HasTypeProfileSlot()
           : script.IsUserJavaScript()));

  // Do not support re-parsing top-level function of a wrapped script.
  DCHECK_IMPLIES(flags.is_toplevel(), !script.is_wrapped());

  return flags;
}

// static
UnoptimizedCompileFlags UnoptimizedCompileFlags::ForScriptCompile(
    Isolate* isolate, Script script) {
  UnoptimizedCompileFlags flags(isolate, script.id());

  flags.SetFlagsForFunctionFromScript(script);
  flags.SetFlagsForToplevelCompile(
      isolate->is_collecting_type_profile(), script.IsUserJavaScript(),
      flags.outer_language_mode(), construct_repl_mode(script.is_repl_mode()));
  if (script.is_wrapped()) {
    flags.set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
  }

  return flags;
}

// static
UnoptimizedCompileFlags UnoptimizedCompileFlags::ForToplevelCompile(
    Isolate* isolate, bool is_user_javascript, LanguageMode language_mode,
    REPLMode repl_mode) {
  UnoptimizedCompileFlags flags(isolate, isolate->GetNextScriptId());
  flags.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(),
                                   is_user_javascript, language_mode,
                                   repl_mode);

  LOG(isolate,
      ScriptEvent(Logger::ScriptEventType::kReserveId, flags.script_id()));
  return flags;
}

// static
UnoptimizedCompileFlags UnoptimizedCompileFlags::ForToplevelFunction(
    const UnoptimizedCompileFlags toplevel_flags,
    const FunctionLiteral* literal) {
  DCHECK(toplevel_flags.is_toplevel());
  DCHECK(!literal->is_toplevel());

  // Replicate the toplevel flags, then setup the function-specific flags.
  UnoptimizedCompileFlags flags = toplevel_flags;
  flags.SetFlagsFromFunction(literal);

  return flags;
}

// static
UnoptimizedCompileFlags UnoptimizedCompileFlags::ForTest(Isolate* isolate) {
  return UnoptimizedCompileFlags(isolate, Script::kTemporaryScriptId);
}

template <typename T>
void UnoptimizedCompileFlags::SetFlagsFromFunction(T function) {
  set_outer_language_mode(function->language_mode());
  set_function_kind(function->kind());
  set_function_syntax_kind(function->syntax_kind());
  set_requires_instance_members_initializer(
      function->requires_instance_members_initializer());
  set_class_scope_has_private_brand(function->class_scope_has_private_brand());
  set_has_static_private_methods_or_accessors(
      function->has_static_private_methods_or_accessors());
  set_is_toplevel(function->is_toplevel());
  set_is_oneshot_iife(function->is_oneshot_iife());
}

void UnoptimizedCompileFlags::SetFlagsForToplevelCompile(
    bool is_collecting_type_profile, bool is_user_javascript,
    LanguageMode language_mode, REPLMode repl_mode) {
  set_allow_lazy_parsing(true);
  set_is_toplevel(true);
  set_collect_type_profile(is_user_javascript && is_collecting_type_profile);
  set_outer_language_mode(
      stricter_language_mode(outer_language_mode(), language_mode));
  set_is_repl_mode((repl_mode == REPLMode::kYes));

  set_block_coverage_enabled(block_coverage_enabled() && is_user_javascript);
}

void UnoptimizedCompileFlags::SetFlagsForFunctionFromScript(Script script) {
  DCHECK_EQ(script_id(), script.id());

  set_is_eval(script.compilation_type() == Script::COMPILATION_TYPE_EVAL);
  set_is_module(script.origin_options().IsModule());
  DCHECK(!(is_eval() && is_module()));

  set_block_coverage_enabled(block_coverage_enabled() &&
                             script.IsUserJavaScript());
}

UnoptimizedCompileState::UnoptimizedCompileState(Isolate* isolate)
    : hash_seed_(HashSeed(isolate)),
      allocator_(isolate->allocator()),
      ast_string_constants_(isolate->ast_string_constants()),
      logger_(isolate->logger()),
      parallel_tasks_(isolate->compiler_dispatcher()->IsEnabled()
                          ? new ParallelTasks(isolate->compiler_dispatcher())
                          : nullptr) {}

UnoptimizedCompileState::UnoptimizedCompileState(
    const UnoptimizedCompileState& other) V8_NOEXCEPT
    : hash_seed_(other.hash_seed()),
      allocator_(other.allocator()),
      ast_string_constants_(other.ast_string_constants()),
      logger_(other.logger()),
      // TODO(leszeks): Should this create a new ParallelTasks instance?
      parallel_tasks_(nullptr) {}

ParseInfo::ParseInfo(const UnoptimizedCompileFlags flags,
                     UnoptimizedCompileState* state)
    : flags_(flags),
      state_(state),
      zone_(std::make_unique<Zone>(state->allocator(), "parser-zone")),
      extension_(nullptr),
      script_scope_(nullptr),
      stack_limit_(0),
      parameters_end_pos_(kNoSourcePosition),
      max_function_literal_id_(kFunctionLiteralIdInvalid),
      character_stream_(nullptr),
      ast_value_factory_(nullptr),
      function_name_(nullptr),
      runtime_call_stats_(nullptr),
      source_range_map_(nullptr),
      literal_(nullptr),
      allow_eval_cache_(false),
      contains_asm_module_(false),
      language_mode_(flags.outer_language_mode()) {
  if (flags.block_coverage_enabled()) {
    AllocateSourceRangeMap();
  }
}

ParseInfo::ParseInfo(Isolate* isolate, const UnoptimizedCompileFlags flags,
                     UnoptimizedCompileState* state)
    : ParseInfo(flags, state) {
  SetPerThreadState(isolate->stack_guard()->real_climit(),
                    isolate->counters()->runtime_call_stats());
}

// static
std::unique_ptr<ParseInfo> ParseInfo::ForToplevelFunction(
    const UnoptimizedCompileFlags flags, UnoptimizedCompileState* compile_state,
    const FunctionLiteral* literal, const AstRawString* function_name) {
  std::unique_ptr<ParseInfo> result(new ParseInfo(flags, compile_state));

  // Clone the function_name AstRawString into the ParseInfo's own
  // AstValueFactory.
  const AstRawString* cloned_function_name =
      result->GetOrCreateAstValueFactory()->CloneFromOtherFactory(
          function_name);

  // Setup function specific details.
  DCHECK(!literal->is_toplevel());
  result->set_function_name(cloned_function_name);

  return result;
}

ParseInfo::~ParseInfo() = default;

DeclarationScope* ParseInfo::scope() const { return literal()->scope(); }

template <typename LocalIsolate>
Handle<Script> ParseInfo::CreateScript(
    LocalIsolate* isolate, Handle<String> source,
    MaybeHandle<FixedArray> maybe_wrapped_arguments,
    ScriptOriginOptions origin_options, NativesFlag natives) {
  // Create a script object describing the script to be compiled.
  DCHECK(flags().script_id() >= 0 ||
         flags().script_id() == Script::kTemporaryScriptId);
  Handle<Script> script =
      isolate->factory()->NewScriptWithId(source, flags().script_id());
  switch (natives) {
    case EXTENSION_CODE:
      script->set_type(Script::TYPE_EXTENSION);
      break;
    case INSPECTOR_CODE:
      script->set_type(Script::TYPE_INSPECTOR);
      break;
    case NOT_NATIVES_CODE:
      break;
  }
  script->set_origin_options(origin_options);
  script->set_is_repl_mode(flags().is_repl_mode());

  DCHECK_EQ(is_wrapped_as_function(), !maybe_wrapped_arguments.is_null());
  if (is_wrapped_as_function()) {
    script->set_wrapped_arguments(*maybe_wrapped_arguments.ToHandleChecked());
  } else if (flags().is_eval()) {
    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
  }

  CheckFlagsForToplevelCompileFromScript(*script,
                                         isolate->is_collecting_type_profile());
  return script;
}

template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<Script> ParseInfo::CreateScript(
        Isolate* isolate, Handle<String> source,
        MaybeHandle<FixedArray> maybe_wrapped_arguments,
        ScriptOriginOptions origin_options, NativesFlag natives);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<Script> ParseInfo::CreateScript(
        LocalIsolate* isolate, Handle<String> source,
        MaybeHandle<FixedArray> maybe_wrapped_arguments,
        ScriptOriginOptions origin_options, NativesFlag natives);

AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() {
  if (!ast_value_factory_.get()) {
    ast_value_factory_.reset(
        new AstValueFactory(zone(), ast_string_constants(), hash_seed()));
  }
  return ast_value_factory();
}

void ParseInfo::AllocateSourceRangeMap() {
  DCHECK(flags().block_coverage_enabled());
  DCHECK_NULL(source_range_map());
  set_source_range_map(zone()->New<SourceRangeMap>(zone()));
}

void ParseInfo::ResetCharacterStream() { character_stream_.reset(); }

void ParseInfo::set_character_stream(
    std::unique_ptr<Utf16CharacterStream> character_stream) {
  DCHECK_NULL(character_stream_);
  character_stream_.swap(character_stream);
}

void ParseInfo::CheckFlagsForToplevelCompileFromScript(
    Script script, bool is_collecting_type_profile) {
  CheckFlagsForFunctionFromScript(script);
  DCHECK(flags().allow_lazy_parsing());
  DCHECK(flags().is_toplevel());
  DCHECK_EQ(flags().collect_type_profile(),
            is_collecting_type_profile && script.IsUserJavaScript());
  DCHECK_EQ(flags().is_repl_mode(), script.is_repl_mode());

  if (script.is_wrapped()) {
    DCHECK_EQ(flags().function_syntax_kind(), FunctionSyntaxKind::kWrapped);
  }
}

void ParseInfo::CheckFlagsForFunctionFromScript(Script script) {
  DCHECK_EQ(flags().script_id(), script.id());
  // We set "is_eval" for wrapped scripts to get an outer declaration scope.
  // This is a bit hacky, but ok since we can't be both eval and wrapped.
  DCHECK_EQ(flags().is_eval() && !script.is_wrapped(),
            script.compilation_type() == Script::COMPILATION_TYPE_EVAL);
  DCHECK_EQ(flags().is_module(), script.origin_options().IsModule());
  DCHECK_IMPLIES(flags().block_coverage_enabled() && script.IsUserJavaScript(),
                 source_range_map() != nullptr);
}

void UnoptimizedCompileState::ParallelTasks::Enqueue(
    ParseInfo* outer_parse_info, const AstRawString* function_name,
    FunctionLiteral* literal) {
  base::Optional<CompilerDispatcher::JobId> job_id =
      dispatcher_->Enqueue(outer_parse_info, function_name, literal);
  if (job_id) {
    enqueued_jobs_.emplace_front(std::make_pair(literal, *job_id));
  }
}

}  // namespace internal
}  // namespace v8
