// 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/unoptimized-compile-job.h"

#include "src/assert-scope.h"
#include "src/base/optional.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler.h"
#include "src/flags.h"
#include "src/global-handles.h"
#include "src/interpreter/interpreter.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/unoptimized-compilation-info.h"
#include "src/utils.h"

namespace v8 {
namespace internal {

namespace {

class OneByteWrapper : public v8::String::ExternalOneByteStringResource {
 public:
  OneByteWrapper(const void* data, int length) : data_(data), length_(length) {}
  ~OneByteWrapper() override = default;

  const char* data() const override {
    return reinterpret_cast<const char*>(data_);
  }

  size_t length() const override { return static_cast<size_t>(length_); }

 private:
  const void* data_;
  int length_;

  DISALLOW_COPY_AND_ASSIGN(OneByteWrapper);
};

class TwoByteWrapper : public v8::String::ExternalStringResource {
 public:
  TwoByteWrapper(const void* data, int length) : data_(data), length_(length) {}
  ~TwoByteWrapper() override = default;

  const uint16_t* data() const override {
    return reinterpret_cast<const uint16_t*>(data_);
  }

  size_t length() const override { return static_cast<size_t>(length_); }

 private:
  const void* data_;
  int length_;

  DISALLOW_COPY_AND_ASSIGN(TwoByteWrapper);
};

}  // namespace

UnoptimizedCompileJob::UnoptimizedCompileJob(Isolate* isolate,
                                             CompilerDispatcherTracer* tracer,
                                             Handle<SharedFunctionInfo> shared,
                                             size_t max_stack_size)
    : CompilerDispatcherJob(Type::kUnoptimizedCompile),
      main_thread_id_(isolate->thread_id().ToInteger()),
      tracer_(tracer),
      allocator_(isolate->allocator()),
      context_(isolate->global_handles()->Create(isolate->context())),
      shared_(isolate->global_handles()->Create(*shared)),
      max_stack_size_(max_stack_size),
      trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
  DCHECK(!shared_->is_toplevel());
  // TODO(rmcilroy): Handle functions with non-empty outer scope info.
  DCHECK(!shared_->HasOuterScopeInfo());
  HandleScope scope(isolate);
  Handle<Script> script(Script::cast(shared_->script()), isolate);
  Handle<String> source(String::cast(script->source()), isolate);
  if (trace_compiler_dispatcher_jobs_) {
    PrintF("UnoptimizedCompileJob[%p] created for ", static_cast<void*>(this));
    ShortPrintOnMainThread();
    PrintF(" in initial state.\n");
  }
}

UnoptimizedCompileJob::~UnoptimizedCompileJob() {
  DCHECK(status() == Status::kInitial || status() == Status::kDone);
  if (!shared_.is_null()) {
    DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
    i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location());
  }
  if (!context_.is_null()) {
    DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
    i::GlobalHandles::Destroy(Handle<Object>::cast(context_).location());
  }
}

bool UnoptimizedCompileJob::IsAssociatedWith(
    Handle<SharedFunctionInfo> shared) const {
  return *shared_ == *shared;
}

void UnoptimizedCompileJob::PrepareOnMainThread(Isolate* isolate) {
  DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
  DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
  DCHECK_EQ(status(), Status::kInitial);
  COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepare);

  if (trace_compiler_dispatcher_jobs_) {
    PrintF("UnoptimizedCompileJob[%p]: Preparing to parse\n",
           static_cast<void*>(this));
  }

  ParseInfo* parse_info = new ParseInfo(isolate, shared_);
  parse_info_.reset(parse_info);

  unicode_cache_.reset(new UnicodeCache());
  parse_info_->set_unicode_cache(unicode_cache_.get());
  parse_info_->set_function_literal_id(shared_->FunctionLiteralId(isolate));
  if (V8_UNLIKELY(FLAG_runtime_stats)) {
    parse_info_->set_runtime_call_stats(new (parse_info_->zone())
                                            RuntimeCallStats());
  }

  Handle<Script> script = parse_info->script();
  HandleScope scope(isolate);

  DCHECK(script->type() != Script::TYPE_NATIVE);
  Handle<String> source(String::cast(script->source()), isolate);
  if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) {
    std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
        isolate, source, shared_->StartPosition(), shared_->EndPosition()));
    parse_info_->set_character_stream(std::move(stream));
  } else {
    source = String::Flatten(isolate, source);
    const void* data;
    int offset = 0;
    int length = source->length();

    // Objects in lo_space don't move, so we can just read the contents from
    // any thread.
    if (isolate->heap()->lo_space()->Contains(*source)) {
      // We need to globalize the handle to the flattened string here, in
      // case it's not referenced from anywhere else.
      source_ = isolate->global_handles()->Create(*source);
      DisallowHeapAllocation no_allocation;
      String::FlatContent content = source->GetFlatContent();
      DCHECK(content.IsFlat());
      data =
          content.IsOneByte()
              ? reinterpret_cast<const void*>(content.ToOneByteVector().start())
              : reinterpret_cast<const void*>(content.ToUC16Vector().start());
    } else {
      // Otherwise, create a copy of the part of the string we'll parse in the
      // zone.
      length = (shared_->EndPosition() - shared_->StartPosition());
      offset = shared_->StartPosition();

      int byte_len = length * (source->IsOneByteRepresentation() ? 1 : 2);
      data = parse_info_->zone()->New(byte_len);

      DisallowHeapAllocation no_allocation;
      String::FlatContent content = source->GetFlatContent();
      DCHECK(content.IsFlat());
      if (content.IsOneByte()) {
        MemCopy(const_cast<void*>(data),
                &content.ToOneByteVector().at(shared_->StartPosition()),
                byte_len);
      } else {
        MemCopy(const_cast<void*>(data),
                &content.ToUC16Vector().at(shared_->StartPosition()), byte_len);
      }
    }
    Handle<String> wrapper;
    if (source->IsOneByteRepresentation()) {
      ExternalOneByteString::Resource* resource =
          new OneByteWrapper(data, length);
      wrapper = isolate->factory()
                    ->NewExternalStringFromOneByte(resource)
                    .ToHandleChecked();
    } else {
      ExternalTwoByteString::Resource* resource =
          new TwoByteWrapper(data, length);
      wrapper = isolate->factory()
                    ->NewExternalStringFromTwoByte(resource)
                    .ToHandleChecked();
    }
    wrapper_ = isolate->global_handles()->Create(*wrapper);
    std::unique_ptr<Utf16CharacterStream> stream(
        ScannerStream::For(isolate, wrapper_, shared_->StartPosition() - offset,
                           shared_->EndPosition() - offset));
    parse_info_->set_character_stream(std::move(stream));
  }

  parser_.reset(new Parser(parse_info_.get()));
  parser_->DeserializeScopeChain(isolate, parse_info_.get(),
                                 parse_info_->maybe_outer_scope_info());

  // Initailize the name after setting up the ast_value_factory.
  Handle<String> name(shared_->Name(), isolate);
  parse_info_->set_function_name(
      parse_info_->ast_value_factory()->GetString(name));

  set_status(Status::kPrepared);
}

void UnoptimizedCompileJob::Compile(bool on_background_thread) {
  DCHECK_EQ(status(), Status::kPrepared);
  COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM(
      tracer_, kCompile,
      parse_info_->end_position() - parse_info_->start_position());
  if (trace_compiler_dispatcher_jobs_) {
    PrintF("UnoptimizedCompileJob[%p]: Compiling\n", static_cast<void*>(this));
  }

  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
  DisallowHandleDereference no_deref;

  parse_info_->set_on_background_thread(on_background_thread);
  uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB;
  parser_->set_stack_limit(stack_limit);
  parse_info_->set_stack_limit(stack_limit);
  parser_->ParseOnBackground(parse_info_.get());

  if (parse_info_->literal() == nullptr) {
    // Parser sets error in pending error handler.
    set_status(Status::kHasErrorsToReport);
    return;
  }

  if (!Compiler::Analyze(parse_info_.get())) {
    parse_info_->pending_error_handler()->set_stack_overflow();
    set_status(Status::kHasErrorsToReport);
    return;
  }

  compilation_job_.reset(interpreter::Interpreter::NewCompilationJob(
      parse_info_.get(), parse_info_->literal(), allocator_, nullptr));

  if (!compilation_job_.get()) {
    parse_info_->pending_error_handler()->set_stack_overflow();
    set_status(Status::kHasErrorsToReport);
    return;
  }

  if (compilation_job_->ExecuteJob() != CompilationJob::SUCCEEDED) {
    parse_info_->pending_error_handler()->set_stack_overflow();
    set_status(Status::kHasErrorsToReport);
    return;
  }

  set_status(Status::kCompiled);
}

void UnoptimizedCompileJob::FinalizeOnMainThread(Isolate* isolate) {
  DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
  DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
  DCHECK_EQ(status(), Status::kCompiled);
  DCHECK_NOT_NULL(parse_info_->literal());
  DCHECK_NOT_NULL(compilation_job_.get());
  COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalize);
  if (trace_compiler_dispatcher_jobs_) {
    PrintF("UnoptimizedCompileJob[%p]: Finalizing compiling\n",
           static_cast<void*>(this));
  }

  Handle<Script> script(Script::cast(shared_->script()), isolate);
  DCHECK_EQ(*parse_info_->script(), shared_->script());

  parser_->UpdateStatistics(isolate, script);
  parse_info_->UpdateBackgroundParseStatisticsOnMainThread(isolate);
  parser_->HandleSourceURLComments(isolate, script);

  {
    HandleScope scope(isolate);
    // Internalize ast values onto the heap.
    parse_info_->ast_value_factory()->Internalize(isolate);
    // Allocate scope infos for the literal.
    DeclarationScope::AllocateScopeInfos(parse_info_.get(), isolate);
    if (compilation_job_->state() == CompilationJob::State::kFailed ||
        !Compiler::FinalizeCompilationJob(compilation_job_.release(), shared_,
                                          isolate)) {
      if (!isolate->has_pending_exception()) isolate->StackOverflow();
      set_status(Status::kFailed);
      return;
    }
  }

  ResetDataOnMainThread(isolate);
  set_status(Status::kDone);
}

void UnoptimizedCompileJob::ReportErrorsOnMainThread(Isolate* isolate) {
  DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
  DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
  DCHECK_EQ(status(), Status::kHasErrorsToReport);

  if (trace_compiler_dispatcher_jobs_) {
    PrintF("UnoptimizedCompileJob[%p]: Reporting Errors\n",
           static_cast<void*>(this));
  }

  // Ensure we report errors in the correct context for the job.
  SaveContext save(isolate);
  isolate->set_context(context());

  Handle<Script> script(Script::cast(shared_->script()), isolate);
  parse_info_->pending_error_handler()->ReportErrors(
      isolate, script, parse_info_->ast_value_factory());

  ResetDataOnMainThread(isolate);
  set_status(Status::kFailed);
}

void UnoptimizedCompileJob::ResetDataOnMainThread(Isolate* isolate) {
  DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
  DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);

  compilation_job_.reset();
  parser_.reset();
  unicode_cache_.reset();
  parse_info_.reset();

  if (!source_.is_null()) {
    DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
    DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
    i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location());
    source_ = Handle<String>::null();
  }
  if (!wrapper_.is_null()) {
    DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
    DCHECK_EQ(isolate->thread_id().ToInteger(), main_thread_id_);
    i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location());
    wrapper_ = Handle<String>::null();
  }
}

void UnoptimizedCompileJob::ResetOnMainThread(Isolate* isolate) {
  if (trace_compiler_dispatcher_jobs_) {
    PrintF("UnoptimizedCompileJob[%p]: Resetting\n", static_cast<void*>(this));
  }

  ResetDataOnMainThread(isolate);
  set_status(Status::kInitial);
}

double UnoptimizedCompileJob::EstimateRuntimeOfNextStepInMs() const {
  switch (status()) {
    case Status::kInitial:
      return tracer_->EstimatePrepareInMs();
    case Status::kPrepared:
      return tracer_->EstimateCompileInMs(parse_info_->end_position() -
                                          parse_info_->start_position());
    case Status::kCompiled:
      return tracer_->EstimateFinalizeInMs();

    case Status::kHasErrorsToReport:
    case Status::kFailed:
    case Status::kDone:
      return 0.0;
  }

  UNREACHABLE();
}

void UnoptimizedCompileJob::ShortPrintOnMainThread() {
  DCHECK_EQ(ThreadId::Current().ToInteger(), main_thread_id_);
  DCHECK(!shared_.is_null());
  shared_->ShortPrint();
}

}  // namespace internal
}  // namespace v8
