// 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/compiler-dispatcher/compiler-dispatcher-job.h"

#include "src/assert-scope.h"
#include "src/compilation-info.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler.h"
#include "src/global-handles.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/unicode-cache.h"
#include "src/zone/zone.h"

namespace v8 {
namespace internal {

CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
                                             Handle<SharedFunctionInfo> shared,
                                             size_t max_stack_size)
    : isolate_(isolate),
      tracer_(isolate_->compiler_dispatcher_tracer()),
      shared_(Handle<SharedFunctionInfo>::cast(
          isolate_->global_handles()->Create(*shared))),
      max_stack_size_(max_stack_size),
      can_compile_on_background_thread_(false) {
  HandleScope scope(isolate_);
  DCHECK(!shared_->outer_scope_info()->IsTheHole(isolate_));
  Handle<Script> script(Script::cast(shared_->script()), isolate_);
  Handle<String> source(String::cast(script->source()), isolate_);
  can_parse_on_background_thread_ =
      source->IsExternalTwoByteString() || source->IsExternalOneByteString();
}

CompilerDispatcherJob::~CompilerDispatcherJob() {
  DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
  DCHECK(status_ == CompileJobStatus::kInitial ||
         status_ == CompileJobStatus::kDone);
  i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location());
}

void CompilerDispatcherJob::PrepareToParseOnMainThread() {
  DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
  DCHECK(status() == CompileJobStatus::kInitial);
  COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToParse);
  HandleScope scope(isolate_);
  unicode_cache_.reset(new UnicodeCache());
  zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME));
  Handle<Script> script(Script::cast(shared_->script()), isolate_);
  DCHECK(script->type() != Script::TYPE_NATIVE);

  Handle<String> source(String::cast(script->source()), isolate_);
  if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) {
    character_stream_.reset(ScannerStream::For(
        source, shared_->start_position(), shared_->end_position()));
  } else {
    source = String::Flatten(source);
    // Have to globalize the reference here, so it survives between function
    // calls.
    source_ = Handle<String>::cast(isolate_->global_handles()->Create(*source));
    character_stream_.reset(ScannerStream::For(
        source_, shared_->start_position(), shared_->end_position()));
  }
  parse_info_.reset(new ParseInfo(zone_.get()));
  parse_info_->set_isolate(isolate_);
  parse_info_->set_character_stream(character_stream_.get());
  parse_info_->set_hash_seed(isolate_->heap()->HashSeed());
  parse_info_->set_is_named_expression(shared_->is_named_expression());
  parse_info_->set_compiler_hints(shared_->compiler_hints());
  parse_info_->set_start_position(shared_->start_position());
  parse_info_->set_end_position(shared_->end_position());
  parse_info_->set_unicode_cache(unicode_cache_.get());
  parse_info_->set_language_mode(shared_->language_mode());

  parser_.reset(new Parser(parse_info_.get()));
  Handle<ScopeInfo> outer_scope_info(
      handle(ScopeInfo::cast(shared_->outer_scope_info())));
  parser_->DeserializeScopeChain(parse_info_.get(),
                                 outer_scope_info->length() > 0
                                     ? MaybeHandle<ScopeInfo>(outer_scope_info)
                                     : MaybeHandle<ScopeInfo>());

  Handle<String> name(String::cast(shared_->name()));
  parse_info_->set_function_name(
      parse_info_->ast_value_factory()->GetString(name));
  status_ = CompileJobStatus::kReadyToParse;
}

void CompilerDispatcherJob::Parse() {
  DCHECK(can_parse_on_background_thread_ ||
         ThreadId::Current().Equals(isolate_->thread_id()));
  DCHECK(status() == CompileJobStatus::kReadyToParse);
  COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
      tracer_, kParse,
      parse_info_->end_position() - parse_info_->start_position());

  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
  std::unique_ptr<DisallowHandleDereference> no_deref;
  // If we can't parse on a background thread, we need to be able to deref the
  // source string.
  if (can_parse_on_background_thread_) {
    no_deref.reset(new DisallowHandleDereference());
  }

  // Nullify the Isolate temporarily so that the parser doesn't accidentally
  // use it.
  parse_info_->set_isolate(nullptr);

  uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;

  parser_->set_stack_limit(stack_limit);
  parser_->ParseOnBackground(parse_info_.get());

  parse_info_->set_isolate(isolate_);

  status_ = CompileJobStatus::kParsed;
}

bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
  DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
  DCHECK(status() == CompileJobStatus::kParsed);
  COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing);

  if (!source_.is_null()) {
    i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
    source_ = Handle<String>::null();
  }

  if (parse_info_->literal() == nullptr) {
    status_ = CompileJobStatus::kFailed;
  } else {
    status_ = CompileJobStatus::kReadyToAnalyse;
  }

  DeferredHandleScope scope(isolate_);
  {
    Handle<Script> script(Script::cast(shared_->script()), isolate_);

    parse_info_->set_script(script);
    Handle<ScopeInfo> outer_scope_info(
        handle(ScopeInfo::cast(shared_->outer_scope_info())));
    if (outer_scope_info->length() > 0) {
      parse_info_->set_outer_scope_info(outer_scope_info);
    }
    parse_info_->set_shared_info(shared_);

    // Do the parsing tasks which need to be done on the main thread. This
    // will also handle parse errors.
    parser_->Internalize(isolate_, script, parse_info_->literal() == nullptr);
    parser_->HandleSourceURLComments(isolate_, script);

    parse_info_->set_character_stream(nullptr);
    parse_info_->set_unicode_cache(nullptr);
    parser_.reset();
    unicode_cache_.reset();
    character_stream_.reset();
  }
  handles_from_parsing_.reset(scope.Detach());

  return status_ != CompileJobStatus::kFailed;
}

bool CompilerDispatcherJob::PrepareToCompileOnMainThread() {
  DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
  DCHECK(status() == CompileJobStatus::kReadyToAnalyse);
  COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);

  compile_info_.reset(
      new CompilationInfo(parse_info_.get(), Handle<JSFunction>::null()));

  DeferredHandleScope scope(isolate_);
  if (Compiler::Analyze(parse_info_.get())) {
    compile_job_.reset(
        Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
  }
  compile_info_->set_deferred_handles(scope.Detach());

  if (!compile_job_.get()) {
    if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
    status_ = CompileJobStatus::kFailed;
    return false;
  }

  can_compile_on_background_thread_ =
      compile_job_->can_execute_on_background_thread();
  status_ = CompileJobStatus::kReadyToCompile;
  return true;
}

void CompilerDispatcherJob::Compile() {
  DCHECK(status() == CompileJobStatus::kReadyToCompile);
  DCHECK(can_compile_on_background_thread_ ||
         ThreadId::Current().Equals(isolate_->thread_id()));
  COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
      tracer_, kCompile, parse_info_->literal()->ast_node_count());

  // Disallowing of handle dereference and heap access dealt with in
  // CompilationJob::ExecuteJob.

  uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;
  compile_job_->set_stack_limit(stack_limit);

  CompilationJob::Status status = compile_job_->ExecuteJob();
  USE(status);

  // Always transition to kCompiled - errors will be reported by
  // FinalizeCompilingOnMainThread.
  status_ = CompileJobStatus::kCompiled;
}

bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() {
  DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
  DCHECK(status() == CompileJobStatus::kCompiled);
  COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling);

  if (compile_job_->state() == CompilationJob::State::kFailed ||
      !Compiler::FinalizeCompilationJob(compile_job_.release())) {
    if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
    status_ = CompileJobStatus::kFailed;
    return false;
  }

  zone_.reset();
  parse_info_.reset();
  compile_info_.reset();
  compile_job_.reset();
  handles_from_parsing_.reset();

  status_ = CompileJobStatus::kDone;
  return true;
}

void CompilerDispatcherJob::ResetOnMainThread() {
  DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));

  parser_.reset();
  unicode_cache_.reset();
  character_stream_.reset();
  parse_info_.reset();
  zone_.reset();
  handles_from_parsing_.reset();
  compile_info_.reset();
  compile_job_.reset();

  if (!source_.is_null()) {
    i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
    source_ = Handle<String>::null();
  }

  status_ = CompileJobStatus::kInitial;
}

}  // namespace internal
}  // namespace v8
