// Copyright (c) 2012, 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.

#include "vm/parser.h"
#include "vm/flags.h"

#ifndef DART_PRECOMPILED_RUNTIME

#include "lib/invocation_mirror.h"
#include "platform/utils.h"
#include "vm/bit_vector.h"
#include "vm/bootstrap.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/frontend/scope_builder.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/growable_array.h"
#include "vm/handles.h"
#include "vm/hash_table.h"
#include "vm/heap/heap.h"
#include "vm/heap/safepoint.h"
#include "vm/isolate.h"
#include "vm/longjump.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/regexp_assembler.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/timeline.h"
#include "vm/zone.h"

namespace dart {

// Quick access to the current thread, isolate and zone.
#define T (thread())
#define I (isolate())
#define Z (zone())

ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
    : thread_(thread),
      function_(function),
      code_(Code::Handle(zone(), function.unoptimized_code())),
      scope_(NULL),
      regexp_compile_data_(NULL),
      function_type_arguments_(NULL),
      parent_type_arguments_(NULL),
      current_context_var_(NULL),
      arg_desc_var_(NULL),
      expression_temp_var_(NULL),
      entry_points_temp_var_(NULL),
      finally_return_temp_var_(NULL),
      dynamic_closure_call_vars_(nullptr),
      guarded_fields_(new ZoneGrowableArray<const Field*>()),
      default_parameter_values_(NULL),
      raw_type_arguments_var_(NULL),
      first_parameter_index_(),
      num_stack_locals_(0),
      have_seen_await_expr_(false),
      kernel_scopes_(NULL) {
  ASSERT(function.IsZoneHandle());
  // Every function has a local variable for the current context.
  LocalVariable* temp = new (zone())
      LocalVariable(function.token_pos(), function.token_pos(),
                    Symbols::CurrentContextVar(), Object::dynamic_type());
  current_context_var_ = temp;

  const bool reify_generic_argument = function.IsGeneric();

  const bool load_optional_arguments = function.HasOptionalParameters();

  const bool check_arguments = function.CanReceiveDynamicInvocation();

  const bool need_argument_descriptor =
      load_optional_arguments || check_arguments || reify_generic_argument;

  if (need_argument_descriptor) {
    arg_desc_var_ = new (zone())
        LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                      Symbols::ArgDescVar(), Object::dynamic_type());
  }
}

void ParsedFunction::AddToGuardedFields(const Field* field) const {
  if ((field->guarded_cid() == kDynamicCid) ||
      (field->guarded_cid() == kIllegalCid)) {
    return;
  }

  for (intptr_t j = 0; j < guarded_fields_->length(); j++) {
    const Field* other = (*guarded_fields_)[j];
    if (field->Original() == other->Original()) {
      // Abort background compilation early if the guarded state of this field
      // has changed during compilation. We will not be able to commit
      // the resulting code anyway.
      if (Compiler::IsBackgroundCompilation()) {
        if (!other->IsConsistentWith(*field)) {
          Compiler::AbortBackgroundCompilation(
              DeoptId::kNone,
              "Field's guarded state changed during compilation");
        }
      }
      return;
    }
  }

  // Note: the list of guarded fields must contain copies during background
  // compilation because we will look at their guarded_cid when copying
  // the array of guarded fields from callee into the caller during
  // inlining.
  ASSERT(!field->IsOriginal() || Thread::Current()->IsMutatorThread());
  guarded_fields_->Add(&Field::ZoneHandle(Z, field->raw()));
}

void ParsedFunction::Bailout(const char* origin, const char* reason) const {
  Report::MessageF(Report::kBailout, Script::Handle(function_.script()),
                   function_.token_pos(), Report::AtLocation,
                   "%s Bailout in %s: %s", origin,
                   String::Handle(function_.name()).ToCString(), reason);
  UNREACHABLE();
}

kernel::ScopeBuildingResult* ParsedFunction::EnsureKernelScopes() {
  if (kernel_scopes_ == NULL) {
    kernel::ScopeBuilder builder(this);
    kernel_scopes_ = builder.BuildScopes();
  }
  return kernel_scopes_;
}

LocalVariable* ParsedFunction::EnsureExpressionTemp() {
  if (!has_expression_temp_var()) {
    LocalVariable* temp =
        new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
                              Symbols::ExprTemp(), Object::dynamic_type());
    ASSERT(temp != NULL);
    set_expression_temp_var(temp);
  }
  ASSERT(has_expression_temp_var());
  return expression_temp_var();
}

LocalVariable* ParsedFunction::EnsureEntryPointsTemp() {
  if (!has_entry_points_temp_var()) {
    LocalVariable* temp = new (Z)
        LocalVariable(function_.token_pos(), function_.token_pos(),
                      Symbols::EntryPointsTemp(), Object::dynamic_type());
    ASSERT(temp != NULL);
    set_entry_points_temp_var(temp);
  }
  ASSERT(has_entry_points_temp_var());
  return entry_points_temp_var();
}

void ParsedFunction::EnsureFinallyReturnTemp(bool is_async) {
  if (!has_finally_return_temp_var()) {
    LocalVariable* temp =
        new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
                              Symbols::FinallyRetVal(), Object::dynamic_type());
    ASSERT(temp != NULL);
    temp->set_is_final();
    if (is_async) {
      temp->set_is_captured();
    }
    set_finally_return_temp_var(temp);
  }
  ASSERT(has_finally_return_temp_var());
}

void ParsedFunction::SetRegExpCompileData(
    RegExpCompileData* regexp_compile_data) {
  ASSERT(regexp_compile_data_ == NULL);
  ASSERT(regexp_compile_data != NULL);
  regexp_compile_data_ = regexp_compile_data;
}

void ParsedFunction::AllocateVariables() {
  ASSERT(!function().IsIrregexpFunction());
  LocalScope* scope = this->scope();
  const intptr_t num_fixed_params = function().num_fixed_parameters();
  const intptr_t num_opt_params = function().NumOptionalParameters();
  const intptr_t num_params = num_fixed_params + num_opt_params;

  // Before we start allocating indices to variables, we'll setup the
  // parameters array, which can be used to access the raw parameters (i.e. not
  // the potentially variables which are in the context)

  raw_parameters_ = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_params);
  for (intptr_t param = 0; param < num_params; ++param) {
    LocalVariable* variable = ParameterVariable(param);
    LocalVariable* raw_parameter = variable;
    if (variable->is_captured()) {
      String& tmp = String::ZoneHandle(Z);
      tmp = Symbols::FromConcat(T, Symbols::OriginalParam(), variable->name());

      RELEASE_ASSERT(scope->LocalLookupVariable(tmp) == NULL);
      raw_parameter = new LocalVariable(
          variable->declaration_token_pos(), variable->token_pos(), tmp,
          variable->type(), variable->parameter_type(),
          variable->parameter_value());
      if (variable->is_explicit_covariant_parameter()) {
        raw_parameter->set_is_explicit_covariant_parameter();
      }
      if (variable->needs_covariant_check_in_method()) {
        raw_parameter->set_needs_covariant_check_in_method();
      }
      raw_parameter->set_type_check_mode(variable->type_check_mode());
      if (function().HasOptionalParameters()) {
        bool ok = scope->AddVariable(raw_parameter);
        ASSERT(ok);

        // Currently our optimizer cannot prove liveness of variables properly
        // when a function has try/catch.  It therefore makes the conservative
        // estimate that all [LocalVariable]s in the frame are live and spills
        // them before call sites (in some shape or form).
        //
        // Since we are guaranteed to not need that, we tell the try/catch
        // sync moves mechanism not to care about this variable.
        //
        // Receiver (this variable) is an exception from this rule because
        // it is immutable and we don't reload captured it from the context but
        // instead use raw_parameter to access it. This means we must still
        // consider it when emitting the catch entry moves.
        const bool is_receiver_var =
            function().HasThisParameter() && receiver_var_ == variable;
        if (!is_receiver_var) {
          raw_parameter->set_is_captured_parameter(true);
        }

      } else {
        raw_parameter->set_index(
            VariableIndex(function().NumParameters() - param));
      }
    }
    raw_parameters_->Add(raw_parameter);
  }
  if (function_type_arguments_ != NULL) {
    LocalVariable* raw_type_args_parameter = function_type_arguments_;
    if (function_type_arguments_->is_captured()) {
      String& tmp = String::ZoneHandle(Z);
      tmp = Symbols::FromConcat(T, Symbols::OriginalParam(),
                                function_type_arguments_->name());

      ASSERT(scope->LocalLookupVariable(tmp) == NULL);
      raw_type_args_parameter =
          new LocalVariable(raw_type_args_parameter->declaration_token_pos(),
                            raw_type_args_parameter->token_pos(), tmp,
                            raw_type_args_parameter->type());
      bool ok = scope->AddVariable(raw_type_args_parameter);
      ASSERT(ok);
    }
    raw_type_arguments_var_ = raw_type_args_parameter;
  }

  // The copy parameters implementation will still write to local variables
  // which we assign indices as with the old CopyParams implementation.
  VariableIndex parameter_index_start;
  VariableIndex reamining_local_variables_start;
  {
    // Compute start indices to parameters and locals, and the number of
    // parameters to copy.
    if (num_opt_params == 0) {
      parameter_index_start = first_parameter_index_ =
          VariableIndex(num_params);
      reamining_local_variables_start = VariableIndex(0);
    } else {
      parameter_index_start = first_parameter_index_ = VariableIndex(0);
      reamining_local_variables_start = VariableIndex(-num_params);
    }
  }

  if (function_type_arguments_ != NULL && num_opt_params > 0) {
    reamining_local_variables_start =
        VariableIndex(reamining_local_variables_start.value() - 1);
  }

  // Allocate parameters and local variables, either in the local frame or
  // in the context(s).
  bool found_captured_variables = false;
  VariableIndex first_local_index =
      VariableIndex(parameter_index_start.value() > 0 ? 0 : -num_params);
  VariableIndex next_free_index = scope->AllocateVariables(
      parameter_index_start, num_params, first_local_index, NULL,
      &found_captured_variables);

  num_stack_locals_ = -next_free_index.value();
}

void ParsedFunction::AllocateIrregexpVariables(intptr_t num_stack_locals) {
  ASSERT(function().IsIrregexpFunction());
  ASSERT(function().NumOptionalParameters() == 0);
  const intptr_t num_params = function().num_fixed_parameters();
  ASSERT(num_params == RegExpMacroAssembler::kParamCount);
  // Compute start indices to parameters and locals, and the number of
  // parameters to copy.
  first_parameter_index_ = VariableIndex(num_params);

  // Frame indices are relative to the frame pointer and are decreasing.
  num_stack_locals_ = num_stack_locals;
}

void ParsedFunction::SetCovariantParameters(
    const BitVector* covariant_parameters) {
  ASSERT(covariant_parameters_ == nullptr);
  ASSERT(covariant_parameters->length() == function_.NumParameters());
  covariant_parameters_ = covariant_parameters;
}

void ParsedFunction::SetGenericCovariantImplParameters(
    const BitVector* generic_covariant_impl_parameters) {
  ASSERT(generic_covariant_impl_parameters_ == nullptr);
  ASSERT(generic_covariant_impl_parameters->length() ==
         function_.NumParameters());
  generic_covariant_impl_parameters_ = generic_covariant_impl_parameters;
}

bool ParsedFunction::IsCovariantParameter(intptr_t i) const {
  ASSERT(covariant_parameters_ != nullptr);
  ASSERT((i >= 0) && (i < function_.NumParameters()));
  return covariant_parameters_->Contains(i);
}

bool ParsedFunction::IsGenericCovariantImplParameter(intptr_t i) const {
  ASSERT(generic_covariant_impl_parameters_ != nullptr);
  ASSERT((i >= 0) && (i < function_.NumParameters()));
  return generic_covariant_impl_parameters_->Contains(i);
}

ParsedFunction::DynamicClosureCallVars*
ParsedFunction::EnsureDynamicClosureCallVars() {
  ASSERT(function().IsDynamicClosureCallDispatcher(thread()));
  if (dynamic_closure_call_vars_ != nullptr) return dynamic_closure_call_vars_;
  dynamic_closure_call_vars_ = new (zone()) DynamicClosureCallVars();

  const auto& type_Dynamic = Object::dynamic_type();
  const auto& type_Function =
      Type::ZoneHandle(zone(), Type::DartFunctionType());
  const auto& type_Smi = Type::ZoneHandle(zone(), Type::SmiType());
#define INIT_FIELD(Name, TypeName, Symbol)                                     \
  dynamic_closure_call_vars_->Name = new (zone())                              \
      LocalVariable(function().token_pos(), function().token_pos(),            \
                    Symbols::DynamicCall##Symbol##Var(), type_##TypeName);
  FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(INIT_FIELD);
#undef INIT_FIELD

  return dynamic_closure_call_vars_;
}

}  // namespace dart

#endif  // DART_PRECOMPILED_RUNTIME
