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

#include "vm/kernel.h"

#include "vm/bit_vector.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/constant_evaluator.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
#include "vm/parser.h"  // For Parser::kParameter* constants.

#if !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace kernel {

KernelLineStartsReader::KernelLineStartsReader(
    const dart::TypedData& line_starts_data,
    dart::Zone* zone)
    : line_starts_data_(line_starts_data) {
  TypedDataElementType type = line_starts_data_.ElementType();
  if (type == kInt8ArrayElement) {
    helper_ = new KernelInt8LineStartsHelper();
  } else if (type == kInt16ArrayElement) {
    helper_ = new KernelInt16LineStartsHelper();
  } else if (type == kInt32ArrayElement) {
    helper_ = new KernelInt32LineStartsHelper();
  } else {
    UNREACHABLE();
  }
}

intptr_t KernelLineStartsReader::LineNumberForPosition(
    intptr_t position) const {
  intptr_t line_count = line_starts_data_.Length();
  intptr_t current_start = 0;
  for (intptr_t i = 0; i < line_count; ++i) {
    current_start += helper_->At(line_starts_data_, i);
    if (current_start > position) {
      // If current_start is greater than the desired position, it means that
      // it is for the line after |position|. However, since line numbers
      // start at 1, we just return |i|.
      return i;
    }

    if (current_start == position) {
      return i + 1;
    }
  }
  return line_count;
}

void KernelLineStartsReader::LocationForPosition(intptr_t position,
                                                 intptr_t* line,
                                                 intptr_t* col) const {
  intptr_t line_count = line_starts_data_.Length();
  intptr_t current_start = 0;
  intptr_t previous_start = 0;
  for (intptr_t i = 0; i < line_count; ++i) {
    current_start += helper_->At(line_starts_data_, i);
    if (current_start > position) {
      *line = i;
      if (col != NULL) {
        *col = position - previous_start + 1;
      }
      return;
    }
    if (current_start == position) {
      *line = i + 1;
      if (col != NULL) {
        *col = 1;
      }
      return;
    }
    previous_start = current_start;
  }

  // If the start of any of the lines did not cross |position|,
  // then it means the position falls on the last line.
  *line = line_count;
  if (col != NULL) {
    *col = position - current_start + 1;
  }
}

void KernelLineStartsReader::TokenRangeAtLine(
    intptr_t source_length,
    intptr_t line_number,
    TokenPosition* first_token_index,
    TokenPosition* last_token_index) const {
  ASSERT(line_number <= line_starts_data_.Length());
  intptr_t cumulative = 0;
  for (intptr_t i = 0; i < line_number; ++i) {
    cumulative += helper_->At(line_starts_data_, i);
  }
  *first_token_index = dart::TokenPosition(cumulative);
  if (line_number == line_starts_data_.Length()) {
    *last_token_index = dart::TokenPosition(source_length);
  } else {
    *last_token_index = dart::TokenPosition(
        cumulative + helper_->At(line_starts_data_, line_number) - 1);
  }
}

int32_t KernelLineStartsReader::KernelInt8LineStartsHelper::At(
    const dart::TypedData& data,
    intptr_t index) const {
  return data.GetInt8(index);
}

int32_t KernelLineStartsReader::KernelInt16LineStartsHelper::At(
    const dart::TypedData& data,
    intptr_t index) const {
  return data.GetInt16(index << 1);
}

int32_t KernelLineStartsReader::KernelInt32LineStartsHelper::At(
    const dart::TypedData& data,
    intptr_t index) const {
  return data.GetInt32(index << 2);
}

class KernelTokenPositionCollector : public KernelReaderHelper {
 public:
  KernelTokenPositionCollector(
      Zone* zone,
      TranslationHelper* translation_helper,
      const Script& script,
      const ExternalTypedData& data,
      intptr_t data_program_offset,
      intptr_t initial_script_index,
      intptr_t record_for_script_id,
      GrowableArray<intptr_t>* record_token_positions_into,
      GrowableArray<intptr_t>* record_yield_positions_into)
      : KernelReaderHelper(zone,
                           translation_helper,
                           script,
                           data,
                           data_program_offset),
        current_script_id_(initial_script_index),
        record_for_script_id_(record_for_script_id),
        record_token_positions_into_(record_token_positions_into),
        record_yield_positions_into_(record_yield_positions_into) {}

  void CollectTokenPositions(intptr_t kernel_offset);

  void RecordTokenPosition(TokenPosition position) override;
  void RecordYieldPosition(TokenPosition position) override;

  void set_current_script_id(intptr_t id) override { current_script_id_ = id; }

 private:
  intptr_t current_script_id_;
  intptr_t record_for_script_id_;
  GrowableArray<intptr_t>* record_token_positions_into_;
  GrowableArray<intptr_t>* record_yield_positions_into_;

  DISALLOW_COPY_AND_ASSIGN(KernelTokenPositionCollector);
};

void KernelTokenPositionCollector::CollectTokenPositions(
    intptr_t kernel_offset) {
  SetOffset(kernel_offset);

  const Tag tag = PeekTag();
  if (tag == kProcedure) {
    ProcedureHelper procedure_helper(this);
    procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
  } else if (tag == kConstructor) {
    ConstructorHelper constructor_helper(this);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
  } else if (tag == kFunctionNode) {
    FunctionNodeHelper function_node_helper(this);
    function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
  } else if (tag == kField) {
    FieldHelper field_helper(this);
    field_helper.ReadUntilExcluding(FieldHelper::kEnd);
  } else if (tag == kClass) {
    ClassHelper class_helper(this);
    class_helper.ReadUntilExcluding(ClassHelper::kEnd);
  } else {
    ReportUnexpectedTag("a class or a member", tag);
    UNREACHABLE();
  }
}

void KernelTokenPositionCollector::RecordTokenPosition(TokenPosition position) {
  if (record_for_script_id_ == current_script_id_ &&
      record_token_positions_into_ != NULL && position.IsReal()) {
    record_token_positions_into_->Add(position.value());
  }
}

void KernelTokenPositionCollector::RecordYieldPosition(TokenPosition position) {
  if (record_for_script_id_ == current_script_id_ &&
      record_yield_positions_into_ != NULL && position.IsReal()) {
    record_yield_positions_into_->Add(position.value());
  }
}

static int LowestFirst(const intptr_t* a, const intptr_t* b) {
  return *a - *b;
}

/**
 * If index exists as sublist in list, sort the sublist from lowest to highest,
 * then copy it, as Smis and without duplicates,
 * to a new Array in Heap::kOld which is returned.
 * Note that the source list is both sorted and de-duplicated as well, but will
 * possibly contain duplicate and unsorted data at the end.
 * Otherwise (when sublist doesn't exist in list) return new empty array.
 */
static RawArray* AsSortedDuplicateFreeArray(GrowableArray<intptr_t>* source) {
  intptr_t size = source->length();
  if (size == 0) {
    return Object::empty_array().raw();
  }

  source->Sort(LowestFirst);

  intptr_t last = 0;
  for (intptr_t current = 1; current < size; ++current) {
    if (source->At(last) != source->At(current)) {
      (*source)[++last] = source->At(current);
    }
  }
  Array& array_object = Array::Handle();
  array_object = Array::New(last + 1, Heap::kOld);
  Smi& smi_value = Smi::Handle();
  for (intptr_t i = 0; i <= last; ++i) {
    smi_value = Smi::New(source->At(i));
    array_object.SetAt(i, smi_value);
  }
  return array_object.raw();
}

static void CollectKernelDataTokenPositions(
    const ExternalTypedData& kernel_data,
    const Script& script,
    const Script& entry_script,
    intptr_t kernel_offset,
    intptr_t data_kernel_offset,
    Zone* zone,
    TranslationHelper* helper,
    GrowableArray<intptr_t>* token_positions,
    GrowableArray<intptr_t>* yield_positions) {
  if (kernel_data.IsNull()) {
    return;
  }

  KernelTokenPositionCollector token_position_collector(
      zone, helper, script, kernel_data, data_kernel_offset,
      entry_script.kernel_script_index(), script.kernel_script_index(),
      token_positions, yield_positions);

  token_position_collector.CollectTokenPositions(kernel_offset);
}

static void CollectBytecodeTokenPositions(
    const Bytecode& bytecode,
    Zone* zone,
    GrowableArray<intptr_t>* token_positions,
    GrowableArray<intptr_t>* yield_positions) {
  BytecodeSourcePositionsIterator iter(zone, bytecode);
  while (iter.MoveNext()) {
    const TokenPosition pos = iter.TokenPos();
    if (pos.IsReal()) {
      // TODO(alexmarkov): collect yield positions from bytecode.
      token_positions->Add(pos.value());
    }
  }
}

static void CollectBytecodeFunctionTokenPositions(
    const Function& function,
    GrowableArray<intptr_t>* token_positions,
    GrowableArray<intptr_t>* yield_positions) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  ASSERT(function.is_declared_in_bytecode());
  if (!function.HasBytecode()) {
    const Object& result = Object::Handle(
        zone, BytecodeReader::ReadFunctionBytecode(thread, function));
    if (!result.IsNull()) {
      Exceptions::PropagateError(Error::Cast(result));
    }
  }
  Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
  ASSERT(!bytecode.IsNull());
  if (bytecode.HasSourcePositions() && !function.IsLocalFunction()) {
    CollectBytecodeTokenPositions(bytecode, zone, token_positions,
                                  yield_positions);
    // Find closure functions in the object pool.
    const ObjectPool& pool = ObjectPool::Handle(zone, bytecode.object_pool());
    Object& object = Object::Handle(zone);
    Function& closure = Function::Handle(zone);
    for (intptr_t i = 0; i < pool.Length(); i++) {
      ObjectPool::EntryType entry_type = pool.TypeAt(i);
      if (entry_type != ObjectPool::EntryType::kTaggedObject) {
        continue;
      }
      object = pool.ObjectAt(i);
      if (object.IsFunction()) {
        closure ^= object.raw();
        if ((closure.kind() == RawFunction::kClosureFunction) &&
            (closure.IsLocalFunction())) {
          bytecode = closure.bytecode();
          ASSERT(!bytecode.IsNull());
          if (bytecode.HasSourcePositions()) {
            CollectBytecodeTokenPositions(bytecode, zone, token_positions,
                                          yield_positions);
          }
        }
      }
    }
  }
}

void CollectTokenPositionsFor(const Script& interesting_script) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  TranslationHelper helper(thread);
  helper.InitFromScript(interesting_script);

  GrowableArray<intptr_t> token_positions(10);
  GrowableArray<intptr_t> yield_positions(1);

  Isolate* isolate = thread->isolate();
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
  Library& lib = Library::Handle(zone);
  Object& entry = Object::Handle(zone);
  Script& entry_script = Script::Handle(zone);
  ExternalTypedData& data = ExternalTypedData::Handle(zone);

  auto& temp_array = Array::Handle(zone);
  auto& temp_field = Field::Handle(zone);
  auto& temp_function = Function::Handle(zone);
  for (intptr_t i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    lib.EnsureTopLevelClassIsFinalized();
    DictionaryIterator it(lib);
    while (it.HasNext()) {
      entry = it.GetNext();
      data = ExternalTypedData::null();
      if (entry.IsClass()) {
        const Class& klass = Class::Cast(entry);
        if (klass.script() == interesting_script.raw()) {
          token_positions.Add(klass.token_pos().value());
        }
        if (klass.is_finalized()) {
          temp_array = klass.fields();
          for (intptr_t i = 0; i < temp_array.Length(); ++i) {
            temp_field ^= temp_array.At(i);
            // TODO(regis): Factorize field handling code.
            if (!temp_field.is_declared_in_bytecode() &&
                temp_field.kernel_offset() <= 0) {
              // Skip artificially injected fields.
              continue;
            }
            entry_script = temp_field.Script();
            if (entry_script.raw() != interesting_script.raw()) {
              continue;
            }
            if (temp_field.is_declared_in_bytecode()) {
              if (temp_field.is_static() && temp_field.has_initializer()) {
                temp_function = temp_field.EnsureInitializerFunction();
                CollectBytecodeFunctionTokenPositions(
                    temp_function, &token_positions, &yield_positions);
              }
            } else {
              data = temp_field.KernelData();
              CollectKernelDataTokenPositions(
                  data, interesting_script, entry_script,
                  temp_field.kernel_offset(),
                  temp_field.KernelDataProgramOffset(), zone, &helper,
                  &token_positions, &yield_positions);
            }
          }
          temp_array = klass.functions();
          for (intptr_t i = 0; i < temp_array.Length(); ++i) {
            temp_function ^= temp_array.At(i);
            // TODO(regis): Factorize function handling code.
            entry_script = temp_function.script();
            if (entry_script.raw() != interesting_script.raw()) {
              continue;
            }
            if (temp_function.is_declared_in_bytecode()) {
              CollectBytecodeFunctionTokenPositions(
                  temp_function, &token_positions, &yield_positions);
            } else {
              data = temp_function.KernelData();
              CollectKernelDataTokenPositions(
                  data, interesting_script, entry_script,
                  temp_function.kernel_offset(),
                  temp_function.KernelDataProgramOffset(), zone, &helper,
                  &token_positions, &yield_positions);
            }
          }
        } else {
          // Class isn't finalized yet: read the data attached to it.
          ASSERT(klass.kernel_offset() > 0);
          data = lib.kernel_data();
          ASSERT(!data.IsNull());
          const intptr_t library_kernel_offset = lib.kernel_offset();
          ASSERT(library_kernel_offset > 0);
          const intptr_t class_offset = klass.kernel_offset();

          entry_script = klass.script();
          if (entry_script.raw() != interesting_script.raw()) {
            continue;
          }
          CollectKernelDataTokenPositions(data, interesting_script,
                                          entry_script, class_offset,
                                          library_kernel_offset, zone, &helper,
                                          &token_positions, &yield_positions);
        }
      } else if (entry.IsFunction()) {
        temp_function ^= entry.raw();
        // TODO(regis): Factorize function handling code.
        entry_script = temp_function.script();
        if (entry_script.raw() != interesting_script.raw()) {
          continue;
        }
        if (temp_function.is_declared_in_bytecode()) {
          CollectBytecodeFunctionTokenPositions(temp_function, &token_positions,
                                                &yield_positions);
        } else {
          data = temp_function.KernelData();
          CollectKernelDataTokenPositions(
              data, interesting_script, entry_script,
              temp_function.kernel_offset(),
              temp_function.KernelDataProgramOffset(), zone, &helper,
              &token_positions, &yield_positions);
        }
      } else if (entry.IsField()) {
        const Field& field = Field::Cast(entry);
        // TODO(regis): Factorize field handling code.
        if (!field.is_declared_in_bytecode() && field.kernel_offset() <= 0) {
          // Skip artificially injected fields.
          continue;
        }
        entry_script = field.Script();
        if (entry_script.raw() != interesting_script.raw()) {
          continue;
        }
        if (field.is_declared_in_bytecode()) {
          if (field.is_static() && field.has_initializer()) {
            temp_function = field.EnsureInitializerFunction();
            CollectBytecodeFunctionTokenPositions(
                temp_function, &token_positions, &yield_positions);
          }
        } else {
          data = field.KernelData();
          CollectKernelDataTokenPositions(
              data, interesting_script, entry_script, field.kernel_offset(),
              field.KernelDataProgramOffset(), zone, &helper, &token_positions,
              &yield_positions);
        }
      }
    }
  }

  Script& script = Script::Handle(zone, interesting_script.raw());
  Array& array_object = Array::Handle(zone);
  array_object = AsSortedDuplicateFreeArray(&token_positions);
  script.set_debug_positions(array_object);
  array_object = AsSortedDuplicateFreeArray(&yield_positions);
  script.set_yield_positions(array_object);
}

class MetadataEvaluator : public KernelReaderHelper {
 public:
  MetadataEvaluator(Zone* zone,
                    TranslationHelper* translation_helper,
                    const Script& script,
                    const ExternalTypedData& data,
                    intptr_t data_program_offset,
                    ActiveClass* active_class)
      : KernelReaderHelper(zone,
                           translation_helper,
                           script,
                           data,
                           data_program_offset),
        type_translator_(this, active_class, /* finalize= */ true),
        constant_evaluator_(this, &type_translator_, active_class, nullptr) {}

  RawObject* EvaluateMetadata(intptr_t kernel_offset,
                              bool is_annotations_offset) {
    SetOffset(kernel_offset);

    // Library and LibraryDependency objects do not have a tag in kernel binary.
    // Synthetic metadata fields corresponding to these objects keep kernel
    // offset of annotations list instead of annotated object.
    if (!is_annotations_offset) {
      const Tag tag = PeekTag();

      if (tag == kClass) {
        ClassHelper class_helper(this);
        class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
      } else if (tag == kProcedure) {
        ProcedureHelper procedure_helper(this);
        procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
      } else if (tag == kField) {
        FieldHelper field_helper(this);
        field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
      } else if (tag == kConstructor) {
        ConstructorHelper constructor_helper(this);
        constructor_helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
      } else {
        FATAL("No support for metadata on this type of kernel node\n");
      }
    }

    return constant_evaluator_.EvaluateAnnotations();
  }

 private:
  TypeTranslator type_translator_;
  ConstantEvaluator constant_evaluator_;

  DISALLOW_COPY_AND_ASSIGN(MetadataEvaluator);
};

RawObject* EvaluateMetadata(const Field& metadata_field,
                            bool is_annotations_offset) {
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();
    TranslationHelper helper(thread);
    Script& script = Script::Handle(zone, metadata_field.Script());
    helper.InitFromScript(script);

    const Class& owner_class = Class::Handle(zone, metadata_field.Owner());
    ActiveClass active_class;
    ActiveClassScope active_class_scope(&active_class, &owner_class);

    MetadataEvaluator metadata_evaluator(
        zone, &helper, script,
        ExternalTypedData::Handle(zone, metadata_field.KernelData()),
        metadata_field.KernelDataProgramOffset(), &active_class);

    return metadata_evaluator.EvaluateMetadata(metadata_field.kernel_offset(),
                                               is_annotations_offset);

  } else {
    return Thread::Current()->StealStickyError();
  }
}

class ParameterDescriptorBuilder : public KernelReaderHelper {
 public:
  ParameterDescriptorBuilder(TranslationHelper* translation_helper,
                             const Script& script,
                             Zone* zone,
                             const ExternalTypedData& data,
                             intptr_t data_program_offset,
                             ActiveClass* active_class)
      : KernelReaderHelper(zone,
                           translation_helper,
                           script,
                           data,
                           data_program_offset),
        type_translator_(this, active_class, /* finalize= */ true),
        constant_evaluator_(this, &type_translator_, active_class, nullptr) {}

  RawObject* BuildParameterDescriptor(intptr_t kernel_offset);

 private:
  TypeTranslator type_translator_;
  ConstantEvaluator constant_evaluator_;

  DISALLOW_COPY_AND_ASSIGN(ParameterDescriptorBuilder);
};

RawObject* ParameterDescriptorBuilder::BuildParameterDescriptor(
    intptr_t kernel_offset) {
  SetOffset(kernel_offset);
  ReadUntilFunctionNode();
  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);
  intptr_t param_count = function_node_helper.total_parameter_count_;
  intptr_t positional_count = ReadListLength();  // read list length.
  intptr_t named_parameter_count = param_count - positional_count;

  const Array& param_descriptor = Array::Handle(
      Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
  for (intptr_t i = 0; i < param_count; ++i) {
    const intptr_t entry_start = i * Parser::kParameterEntrySize;

    if (i == positional_count) {
      intptr_t named_parameter_count_check =
          ReadListLength();  // read list length.
      ASSERT(named_parameter_count_check == named_parameter_count);
    }

    // Read ith variable declaration.
    intptr_t param_kernel_offset = reader_.offset();
    VariableDeclarationHelper helper(this);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
    param_descriptor.SetAt(entry_start + Parser::kParameterIsFinalOffset,
                           helper.IsFinal() ? Bool::True() : Bool::False());

    Tag tag = ReadTag();  // read (first part of) initializer.
    if (tag == kSomething) {
      // this will (potentially) read the initializer, but reset the position.
      Instance& constant = Instance::ZoneHandle(
          zone_, constant_evaluator_.EvaluateExpression(ReaderOffset()));
      SkipExpression();  // read (actual) initializer.
      param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                             constant);
    } else {
      param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                             Object::null_instance());
    }

    if (FLAG_enable_mirrors && (helper.annotation_count_ > 0)) {
      AlternativeReadingScope alt(&reader_, param_kernel_offset);
      VariableDeclarationHelper helper(this);
      helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
      Object& metadata =
          Object::ZoneHandle(zone_, constant_evaluator_.EvaluateAnnotations());
      param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
                             metadata);
    } else {
      param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
                             Object::null_instance());
    }
  }
  return param_descriptor.raw();
}

RawObject* BuildParameterDescriptor(const Function& function) {
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();
    TranslationHelper helper(thread);
    Script& script = Script::Handle(zone, function.script());
    helper.InitFromScript(script);

    const Class& owner_class = Class::Handle(zone, function.Owner());
    ActiveClass active_class;
    ActiveClassScope active_class_scope(&active_class, &owner_class);

    ParameterDescriptorBuilder builder(
        &helper, Script::Handle(zone, function.script()), zone,
        ExternalTypedData::Handle(zone, function.KernelData()),
        function.KernelDataProgramOffset(), &active_class);

    return builder.BuildParameterDescriptor(function.kernel_offset());
  } else {
    return Thread::Current()->StealStickyError();
  }
}

void ReadParameterCovariance(const Function& function,
                             BitVector* is_covariant,
                             BitVector* is_generic_covariant_impl) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  const intptr_t num_params = function.NumParameters();
  ASSERT(is_covariant->length() == num_params);
  ASSERT(is_generic_covariant_impl->length() == num_params);

  const auto& script = Script::Handle(zone, function.script());
  TranslationHelper translation_helper(thread);
  translation_helper.InitFromScript(script);

  if (function.is_declared_in_bytecode()) {
    BytecodeReaderHelper bytecode_reader_helper(&translation_helper, nullptr,
                                                nullptr);
    bytecode_reader_helper.ReadParameterCovariance(function, is_covariant,
                                                   is_generic_covariant_impl);
    return;
  }

  KernelReaderHelper reader_helper(
      zone, &translation_helper, script,
      ExternalTypedData::Handle(zone, function.KernelData()),
      function.KernelDataProgramOffset());

  reader_helper.SetOffset(function.kernel_offset());
  reader_helper.ReadUntilFunctionNode();

  FunctionNodeHelper function_node_helper(&reader_helper);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);

  // Positional.
  const intptr_t num_positional_params = reader_helper.ReadListLength();
  intptr_t param_index = function.NumImplicitParameters();
  for (intptr_t i = 0; i < num_positional_params; ++i, ++param_index) {
    VariableDeclarationHelper helper(&reader_helper);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);

    if (helper.IsCovariant()) {
      is_covariant->Add(param_index);
    }
    if (helper.IsGenericCovariantImpl()) {
      is_generic_covariant_impl->Add(param_index);
    }
  }

  // Named.
  const intptr_t num_named_params = reader_helper.ReadListLength();
  for (intptr_t i = 0; i < num_named_params; ++i, ++param_index) {
    VariableDeclarationHelper helper(&reader_helper);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);

    if (helper.IsCovariant()) {
      is_covariant->Add(param_index);
    }
    if (helper.IsGenericCovariantImpl()) {
      is_generic_covariant_impl->Add(param_index);
    }
  }
}

bool NeedsDynamicInvocationForwarder(const Function& function) {
  Zone* zone = Thread::Current()->zone();

  // Covariant parameters (both explicitly covariant and generic-covariant-impl)
  // are checked in the body of a function and therefore don't need checks in a
  // dynamic invocation forwarder. So dynamic invocation forwarder is only
  // needed if there are non-covariant parameters of non-top type.

  ASSERT(!function.IsImplicitGetterFunction());
  if (function.IsImplicitSetterFunction()) {
    const auto& field = Field::Handle(zone, function.accessor_field());
    return !(field.is_covariant() || field.is_generic_covariant_impl());
  }

  const auto& type_params =
      TypeArguments::Handle(zone, function.type_parameters());
  if (!type_params.IsNull()) {
    auto& type_param = TypeParameter::Handle(zone);
    auto& bound = AbstractType::Handle(zone);
    for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
      type_param ^= type_params.TypeAt(i);
      bound = type_param.bound();
      if (!bound.IsTopType() && !type_param.IsGenericCovariantImpl()) {
        return true;
      }
    }
  }

  const intptr_t num_params = function.NumParameters();
  BitVector is_covariant(zone, num_params);
  BitVector is_generic_covariant_impl(zone, num_params);
  ReadParameterCovariance(function, &is_covariant, &is_generic_covariant_impl);

  auto& type = AbstractType::Handle(zone);
  for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
    type = function.ParameterTypeAt(i);
    if (!type.IsTopType() && !is_generic_covariant_impl.Contains(i) &&
        !is_covariant.Contains(i)) {
      return true;
    }
  }

  return false;
}

static ProcedureAttributesMetadata ProcedureAttributesOf(
    Zone* zone,
    const Script& script,
    const ExternalTypedData& kernel_data,
    intptr_t kernel_data_program_offset,
    intptr_t kernel_offset) {
  TranslationHelper translation_helper(Thread::Current());
  translation_helper.InitFromScript(script);
  KernelReaderHelper reader_helper(zone, &translation_helper, script,
                                   kernel_data, kernel_data_program_offset);
  ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper(
      &reader_helper);
  ProcedureAttributesMetadata attrs =
      procedure_attributes_metadata_helper.GetProcedureAttributes(
          kernel_offset);
  return attrs;
}

ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
                                                  Zone* zone) {
  const Script& script = Script::Handle(zone, function.script());
  return ProcedureAttributesOf(
      zone, script, ExternalTypedData::Handle(zone, function.KernelData()),
      function.KernelDataProgramOffset(), function.kernel_offset());
}

ProcedureAttributesMetadata ProcedureAttributesOf(const Field& field,
                                                  Zone* zone) {
  const Class& parent = Class::Handle(zone, field.Owner());
  const Script& script = Script::Handle(zone, parent.script());
  return ProcedureAttributesOf(
      zone, script, ExternalTypedData::Handle(zone, field.KernelData()),
      field.KernelDataProgramOffset(), field.kernel_offset());
}

}  // namespace kernel
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
