// Copyright 2017 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/preparsed-scope-data.h"

#include "src/ast/scopes.h"
#include "src/ast/variables.h"
#include "src/handles.h"
#include "src/objects-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/parsing/preparser.h"

namespace v8 {
namespace internal {

namespace {

class ScopeCallsSloppyEvalField : public BitField<bool, 0, 1> {};
class InnerScopeCallsEvalField
    : public BitField<bool, ScopeCallsSloppyEvalField::kNext, 1> {};

class VariableIsUsedField : public BitField16<bool, 0, 1> {};
class VariableMaybeAssignedField
    : public BitField16<bool, VariableIsUsedField::kNext, 1> {};
class VariableContextAllocatedField
    : public BitField16<bool, VariableMaybeAssignedField::kNext, 1> {};

const int kMagicValue = 0xc0de0de;

#ifdef DEBUG
const size_t kUint32Size = 5;
const size_t kUint8Size = 2;
#else
const size_t kUint32Size = 4;
const size_t kUint8Size = 1;
#endif

const int kSkippableFunctionDataSize = 4 * kUint32Size + 1 * kUint8Size;

STATIC_ASSERT(LANGUAGE_END == 2);
class LanguageField : public BitField<int, 0, 1> {};
class UsesSuperField : public BitField<bool, LanguageField::kNext, 1> {};

}  // namespace

/*

  Internal data format for the backing store of ProducedPreparsedScopeData and
  PreParsedScopeData::scope_data (on the heap):

  (Skippable function data:)
  ------------------------------------
  | scope_data_start                 |
  ------------------------------------
  | data for inner function 1        |
  | ...                              |
  ------------------------------------
  | data for inner function n        |
  | ...                              |
  ------------------------------------
  (Scope allocation data:)             << scope_data_start points here
  ------------------------------------
  magic value
  ------------------------------------
  scope positions
  ------------------------------------
  | scope type << only in debug      |
  | eval                             |
  | ----------------------           |
  | | data for variables |           |
  | | ...                |           |
  | ----------------------           |
  ------------------------------------
  ------------------------------------
  | data for inner scope 1           | << but not for function scopes
  | ...                              |
  ------------------------------------
  ...
  ------------------------------------
  | data for inner scope m           |
  | ...                              |
  ------------------------------------

  PreParsedScopeData::child_data is an array of PreParsedScopeData objects, one
  for each skippable inner function.

  ConsumedPreParsedScopeData wraps a PreParsedScopeData and reads data from it.

 */

void ProducedPreParsedScopeData::ByteData::WriteUint32(uint32_t data) {
#ifdef DEBUG
  // Save expected item size in debug mode.
  backing_store_.push_back(kUint32Size);
#endif
  const uint8_t* d = reinterpret_cast<uint8_t*>(&data);
  for (int i = 0; i < 4; ++i) {
    backing_store_.push_back(*d++);
  }
}

void ProducedPreParsedScopeData::ByteData::OverwriteFirstUint32(uint32_t data) {
  size_t position = 0;
#ifdef DEBUG
  // Check that that position already holds an item of the expected size.
  DCHECK_GE(backing_store_.size(), kUint32Size);
  DCHECK_EQ(backing_store_[0], kUint32Size);
  ++position;
#endif
  const uint8_t* d = reinterpret_cast<uint8_t*>(&data);
  for (size_t i = 0; i < 4; ++i) {
    backing_store_[position + i] = *d++;
  }
}

void ProducedPreParsedScopeData::ByteData::WriteUint8(uint8_t data) {
#ifdef DEBUG
  // Save expected item size in debug mode.
  backing_store_.push_back(kUint8Size);
#endif
  backing_store_.push_back(data);
}

Handle<PodArray<uint8_t>> ProducedPreParsedScopeData::ByteData::Serialize(
    Isolate* isolate) const {
  Handle<PodArray<uint8_t>> array = PodArray<uint8_t>::New(
      isolate, static_cast<int>(backing_store_.size()), TENURED);

  DisallowHeapAllocation no_gc;
  PodArray<uint8_t>* raw_array = *array;

  int i = 0;
  for (uint8_t item : backing_store_) {
    raw_array->set(i++, item);
  }
  return array;
}

ProducedPreParsedScopeData::ProducedPreParsedScopeData(
    Zone* zone, ProducedPreParsedScopeData* parent)
    : parent_(parent),
      byte_data_(new (zone) ByteData(zone)),
      data_for_inner_functions_(zone),
      bailed_out_(false) {
  if (parent != nullptr) {
    parent->data_for_inner_functions_.push_back(this);
  }
  // Reserve space for scope_data_start, written later:
  byte_data_->WriteUint32(0);
}

// Create a ProducedPreParsedScopeData which is just a proxy for a previous
// produced PreParsedScopeData.
ProducedPreParsedScopeData::ProducedPreParsedScopeData(
    Handle<PreParsedScopeData> data, Zone* zone)
    : parent_(nullptr),
      byte_data_(nullptr),
      data_for_inner_functions_(zone),
      bailed_out_(false),
      previously_produced_preparsed_scope_data_(data) {}

ProducedPreParsedScopeData::DataGatheringScope::DataGatheringScope(
    DeclarationScope* function_scope, PreParser* preparser)
    : function_scope_(function_scope),
      preparser_(preparser),
      produced_preparsed_scope_data_(nullptr) {
  if (FLAG_preparser_scope_analysis) {
    ProducedPreParsedScopeData* parent =
        preparser->produced_preparsed_scope_data();
    Zone* main_zone = preparser->main_zone();
    produced_preparsed_scope_data_ =
        new (main_zone) ProducedPreParsedScopeData(main_zone, parent);
    preparser->set_produced_preparsed_scope_data(
        produced_preparsed_scope_data_);
    function_scope->set_produced_preparsed_scope_data(
        produced_preparsed_scope_data_);
  }
}

ProducedPreParsedScopeData::DataGatheringScope::~DataGatheringScope() {
  if (FLAG_preparser_scope_analysis) {
    preparser_->set_produced_preparsed_scope_data(
        produced_preparsed_scope_data_->parent_);
  }
}

void ProducedPreParsedScopeData::DataGatheringScope::MarkFunctionAsSkippable(
    int end_position, int num_inner_functions) {
  DCHECK(FLAG_preparser_scope_analysis);
  DCHECK_NOT_NULL(produced_preparsed_scope_data_);
  DCHECK_NOT_NULL(produced_preparsed_scope_data_->parent_);
  produced_preparsed_scope_data_->parent_->AddSkippableFunction(
      function_scope_->start_position(), end_position,
      function_scope_->num_parameters(), num_inner_functions,
      function_scope_->language_mode(), function_scope_->uses_super_property());
}

void ProducedPreParsedScopeData::AddSkippableFunction(
    int start_position, int end_position, int num_parameters,
    int num_inner_functions, LanguageMode language_mode,
    bool uses_super_property) {
  DCHECK(FLAG_preparser_scope_analysis);
  DCHECK(previously_produced_preparsed_scope_data_.is_null());

  if (bailed_out_) {
    return;
  }

  byte_data_->WriteUint32(start_position);
  byte_data_->WriteUint32(end_position);
  byte_data_->WriteUint32(num_parameters);
  byte_data_->WriteUint32(num_inner_functions);

  uint8_t language_and_super = LanguageField::encode(language_mode) |
                               UsesSuperField::encode(uses_super_property);

  byte_data_->WriteUint8(language_and_super);
}

void ProducedPreParsedScopeData::SaveScopeAllocationData(
    DeclarationScope* scope) {
  DCHECK(FLAG_preparser_scope_analysis);
  DCHECK(previously_produced_preparsed_scope_data_.is_null());
  // The data contains a uint32 (reserved space for scope_data_start) and
  // function data items, kSkippableFunctionDataSize each.
  DCHECK_GE(byte_data_->size(), kUint32Size);
  DCHECK_LE(byte_data_->size(), std::numeric_limits<uint32_t>::max());
  DCHECK_EQ(byte_data_->size() % kSkippableFunctionDataSize, kUint32Size);

  if (bailed_out_) {
    return;
  }

  uint32_t scope_data_start = static_cast<uint32_t>(byte_data_->size());

  // If there are no skippable inner functions, we don't need to save anything.
  if (scope_data_start == kUint32Size) {
    return;
  }

  byte_data_->OverwriteFirstUint32(scope_data_start);

  // For a data integrity check, write a value between data about skipped inner
  // funcs and data about variables.
  byte_data_->WriteUint32(kMagicValue);
  byte_data_->WriteUint32(scope->start_position());
  byte_data_->WriteUint32(scope->end_position());

  SaveDataForScope(scope);
}

MaybeHandle<PreParsedScopeData> ProducedPreParsedScopeData::Serialize(
    Isolate* isolate) const {
  if (!previously_produced_preparsed_scope_data_.is_null()) {
    DCHECK(!bailed_out_);
    DCHECK_EQ(data_for_inner_functions_.size(), 0);
    return previously_produced_preparsed_scope_data_;
  }
  if (bailed_out_) {
    return MaybeHandle<PreParsedScopeData>();
  }

  DCHECK(!ThisOrParentBailedOut());

  if (byte_data_->size() <= kUint32Size) {
    // The data contains only the placeholder.
    return MaybeHandle<PreParsedScopeData>();
  }

  Handle<PreParsedScopeData> data = isolate->factory()->NewPreParsedScopeData();

  Handle<PodArray<uint8_t>> scope_data_array = byte_data_->Serialize(isolate);
  data->set_scope_data(*scope_data_array);

  int child_data_length = static_cast<int>(data_for_inner_functions_.size());
  if (child_data_length == 0) {
    data->set_child_data(*(isolate->factory()->empty_fixed_array()));
  } else {
    Handle<FixedArray> child_array =
        isolate->factory()->NewFixedArray(child_data_length, TENURED);
    int i = 0;
    for (const auto& item : data_for_inner_functions_) {
      MaybeHandle<PreParsedScopeData> maybe_child_data =
          item->Serialize(isolate);
      if (maybe_child_data.is_null()) {
        child_array->set(i++, *(isolate->factory()->null_value()));
      } else {
        Handle<PreParsedScopeData> child_data =
            maybe_child_data.ToHandleChecked();
        child_array->set(i++, *child_data);
      }
    }
    data->set_child_data(*child_array);
  }

  return data;
}

bool ProducedPreParsedScopeData::ScopeNeedsData(Scope* scope) {
  if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
    // Default constructors don't need data (they cannot contain inner functions
    // defined by the user). Other functions do.
    return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
  }
  if (!scope->is_hidden()) {
    for (Variable* var : *scope->locals()) {
      if (IsDeclaredVariableMode(var->mode())) {
        return true;
      }
    }
  }
  for (Scope* inner = scope->inner_scope(); inner != nullptr;
       inner = inner->sibling()) {
    if (ScopeNeedsData(inner)) {
      return true;
    }
  }
  return false;
}

bool ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(Scope* scope) {
  // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
  // those Scopes which have their own ProducedPreParsedScopeData object. This
  // logic ensures that the scope allocation data is consistent with the
  // skippable function data (both agree on where the lazy function boundaries
  // are).
  if (scope->scope_type() != ScopeType::FUNCTION_SCOPE) {
    return false;
  }
  DeclarationScope* declaration_scope = scope->AsDeclarationScope();
  return !declaration_scope->is_arrow_scope() &&
         declaration_scope->produced_preparsed_scope_data() != nullptr;
}

void ProducedPreParsedScopeData::SaveDataForScope(Scope* scope) {
  DCHECK_NE(scope->end_position(), kNoSourcePosition);

  // We're not trying to save data for default constructors because the
  // PreParser doesn't construct them.
  DCHECK_IMPLIES(scope->scope_type() == ScopeType::FUNCTION_SCOPE,
                 (scope->AsDeclarationScope()->function_kind() &
                  kDefaultConstructor) == 0);

  if (!ScopeNeedsData(scope)) {
    return;
  }

#ifdef DEBUG
  byte_data_->WriteUint8(scope->scope_type());
#endif

  uint8_t eval =
      ScopeCallsSloppyEvalField::encode(
          scope->is_declaration_scope() &&
          scope->AsDeclarationScope()->calls_sloppy_eval()) |
      InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval());
  byte_data_->WriteUint8(eval);

  if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
    Variable* function = scope->AsDeclarationScope()->function_var();
    if (function != nullptr) {
      SaveDataForVariable(function);
    }
  }

  for (Variable* var : *scope->locals()) {
    if (IsDeclaredVariableMode(var->mode())) {
      SaveDataForVariable(var);
    }
  }

  SaveDataForInnerScopes(scope);
}

void ProducedPreParsedScopeData::SaveDataForVariable(Variable* var) {
#ifdef DEBUG
  // Store the variable name in debug mode; this way we can check that we
  // restore data to the correct variable.
  const AstRawString* name = var->raw_name();
  byte_data_->WriteUint32(name->length());
  for (int i = 0; i < name->length(); ++i) {
    byte_data_->WriteUint8(name->raw_data()[i]);
  }
#endif
  // FIXME(marja): Only 3 bits needed, not a full byte.
  byte variable_data = VariableIsUsedField::encode(var->is_used()) |
                       VariableMaybeAssignedField::encode(
                           var->maybe_assigned() == kMaybeAssigned) |
                       VariableContextAllocatedField::encode(
                           var->has_forced_context_allocation());

  byte_data_->WriteUint8(variable_data);
}

void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
  // Inner scopes are stored in the reverse order, but we'd like to write the
  // data in the logical order. There might be many inner scopes, so we don't
  // want to recurse here.
  std::vector<Scope*> scopes;
  for (Scope* inner = scope->inner_scope(); inner != nullptr;
       inner = inner->sibling()) {
    if (ScopeIsSkippableFunctionScope(inner)) {
      // Don't save data about function scopes, since they'll have their own
      // ProducedPreParsedScopeData where their data is saved.
      DCHECK(inner->AsDeclarationScope()->produced_preparsed_scope_data() !=
             nullptr);
      continue;
    }
    scopes.push_back(inner);
  }
  for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
    SaveDataForScope(*it);
  }
}

ConsumedPreParsedScopeData::ByteData::ReadingScope::ReadingScope(
    ConsumedPreParsedScopeData* parent)
    : ReadingScope(parent->scope_data_.get(), parent->data_->scope_data()) {}

int32_t ConsumedPreParsedScopeData::ByteData::ReadUint32() {
  DCHECK_NOT_NULL(data_);
  DCHECK_GE(RemainingBytes(), kUint32Size);
#ifdef DEBUG
  // Check that there indeed is an integer following.
  DCHECK_EQ(data_->get(index_++), kUint32Size);
#endif
  int32_t result = 0;
  byte* p = reinterpret_cast<byte*>(&result);
  for (int i = 0; i < 4; ++i) {
    *p++ = data_->get(index_++);
  }
  return result;
}

uint8_t ConsumedPreParsedScopeData::ByteData::ReadUint8() {
  DCHECK_NOT_NULL(data_);
  DCHECK_GE(RemainingBytes(), kUint8Size);
#ifdef DEBUG
  // Check that there indeed is a byte following.
  DCHECK_EQ(data_->get(index_++), kUint8Size);
#endif
  return data_->get(index_++);
}

ConsumedPreParsedScopeData::ConsumedPreParsedScopeData()
    : scope_data_(new ByteData()), child_index_(0) {}

ConsumedPreParsedScopeData::~ConsumedPreParsedScopeData() {}

void ConsumedPreParsedScopeData::SetData(Handle<PreParsedScopeData> data) {
  DCHECK(data->IsPreParsedScopeData());
  data_ = data;
#ifdef DEBUG
  ByteData::ReadingScope reading_scope(this);
  int scope_data_start = scope_data_->ReadUint32();
  scope_data_->SetPosition(scope_data_start);
  DCHECK_EQ(scope_data_->ReadUint32(), kMagicValue);
#endif
  // The first data item is scope_data_start. Skip over it.
  scope_data_->SetPosition(kUint32Size);
}

ProducedPreParsedScopeData*
ConsumedPreParsedScopeData::GetDataForSkippableFunction(
    Zone* zone, int start_position, int* end_position, int* num_parameters,
    int* num_inner_functions, bool* uses_super_property,
    LanguageMode* language_mode) {
  // The skippable function *must* be the next function in the data. Use the
  // start position as a sanity check.
  ByteData::ReadingScope reading_scope(this);
  CHECK_GE(scope_data_->RemainingBytes(), kSkippableFunctionDataSize);
  int start_position_from_data = scope_data_->ReadUint32();
  CHECK_EQ(start_position, start_position_from_data);

  *end_position = scope_data_->ReadUint32();
  DCHECK_GT(*end_position, start_position);
  *num_parameters = scope_data_->ReadUint32();
  *num_inner_functions = scope_data_->ReadUint32();

  uint8_t language_and_super = scope_data_->ReadUint8();
  *language_mode = LanguageMode(LanguageField::decode(language_and_super));
  *uses_super_property = UsesSuperField::decode(language_and_super);

  // Retrieve the corresponding PreParsedScopeData and associate it to the
  // skipped function. If the skipped functions contains inner functions, those
  // can be skipped when the skipped function is eagerly parsed.
  FixedArray* children = data_->child_data();
  CHECK_GT(children->length(), child_index_);
  Object* child_data = children->get(child_index_++);
  if (!child_data->IsPreParsedScopeData()) {
    return nullptr;
  }
  Handle<PreParsedScopeData> child_data_handle(
      PreParsedScopeData::cast(child_data));
  return new (zone) ProducedPreParsedScopeData(child_data_handle, zone);
}

void ConsumedPreParsedScopeData::RestoreScopeAllocationData(
    DeclarationScope* scope) {
  DCHECK(FLAG_preparser_scope_analysis);
  DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
  DCHECK(!data_.is_null());

  ByteData::ReadingScope reading_scope(this);

  int magic_value_from_data = scope_data_->ReadUint32();
  // Check that we've consumed all inner function data.
  CHECK_EQ(magic_value_from_data, kMagicValue);

  int start_position_from_data = scope_data_->ReadUint32();
  int end_position_from_data = scope_data_->ReadUint32();
  CHECK_EQ(start_position_from_data, scope->start_position());
  CHECK_EQ(end_position_from_data, scope->end_position());

  RestoreData(scope);

  // Check that we consumed all scope data.
  DCHECK_EQ(scope_data_->RemainingBytes(), 0);
}

void ConsumedPreParsedScopeData::SkipFunctionDataForTesting() {
  ByteData::ReadingScope reading_scope(this);
  scope_data_->SetPosition(0);
  uint32_t scope_data_start = scope_data_->ReadUint32();
  scope_data_->SetPosition(scope_data_start);
}

void ConsumedPreParsedScopeData::RestoreData(Scope* scope) {
  if (scope->is_declaration_scope() &&
      scope->AsDeclarationScope()->is_skipped_function()) {
    return;
  }

  // It's possible that scope is not present in the data at all (since PreParser
  // doesn't create the corresponding scope). In this case, the Scope won't
  // contain any variables for which we need the data.
  if (!ProducedPreParsedScopeData::ScopeNeedsData(scope)) {
    return;
  }

  if (scope_data_->RemainingBytes() < kUint8Size) {
    // Temporary debugging code for detecting inconsistent data. Write debug
    // information on the stack, then crash.
    data_->GetIsolate()->PushStackTraceAndDie(0xc0defee, nullptr, nullptr,
                                              0xc0defee);
  }

  // scope_type is stored only in debug mode.
  CHECK_GE(scope_data_->RemainingBytes(), kUint8Size);
  DCHECK_EQ(scope_data_->ReadUint8(), scope->scope_type());

  uint32_t eval = scope_data_->ReadUint8();
  if (ScopeCallsSloppyEvalField::decode(eval)) {
    scope->RecordEvalCall();
  }
  if (InnerScopeCallsEvalField::decode(eval)) {
    scope->RecordInnerScopeEvalCall();
  }

  if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
    Variable* function = scope->AsDeclarationScope()->function_var();
    if (function != nullptr) {
      RestoreDataForVariable(function);
    }
  }

  for (Variable* var : *scope->locals()) {
    if (IsDeclaredVariableMode(var->mode())) {
      RestoreDataForVariable(var);
    }
  }

  RestoreDataForInnerScopes(scope);
}

void ConsumedPreParsedScopeData::RestoreDataForVariable(Variable* var) {
#ifdef DEBUG
  const AstRawString* name = var->raw_name();
  DCHECK_EQ(scope_data_->ReadUint32(), static_cast<uint32_t>(name->length()));
  for (int i = 0; i < name->length(); ++i) {
    DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
  }
#endif
  CHECK_GE(scope_data_->RemainingBytes(), kUint8Size);
  uint8_t variable_data = scope_data_->ReadUint8();
  if (VariableIsUsedField::decode(variable_data)) {
    var->set_is_used();
  }
  if (VariableMaybeAssignedField::decode(variable_data)) {
    var->set_maybe_assigned();
  }
  if (VariableContextAllocatedField::decode(variable_data)) {
    var->ForceContextAllocation();
  }
}

void ConsumedPreParsedScopeData::RestoreDataForInnerScopes(Scope* scope) {
  std::vector<Scope*> scopes;
  for (Scope* inner = scope->inner_scope(); inner != nullptr;
       inner = inner->sibling()) {
    scopes.push_back(inner);
  }
  for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
    RestoreData(*it);
  }
}

}  // namespace internal
}  // namespace v8
