// Copyright 2020 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/heap/factory-base.h"

#include "src/ast/ast-source-ranges.h"
#include "src/ast/ast.h"
#include "src/execution/local-isolate.h"
#include "src/handles/handles-inl.h"
#include "src/heap/factory.h"
#include "src/heap/heap-inl.h"
#include "src/heap/local-factory-inl.h"
#include "src/heap/memory-chunk.h"
#include "src/heap/read-only-heap.h"
#include "src/logging/local-logger.h"
#include "src/logging/log.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/oddball.h"
#include "src/objects/shared-function-info-inl.h"
#include "src/objects/source-text-module.h"
#include "src/objects/string-inl.h"
#include "src/objects/string.h"
#include "src/objects/template-objects-inl.h"

namespace v8 {
namespace internal {

template <typename Impl>
template <AllocationType allocation>
Handle<HeapNumber> FactoryBase<Impl>::NewHeapNumber() {
  STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize);
  Map map = read_only_roots().heap_number_map();
  HeapObject result = AllocateRawWithImmortalMap(HeapNumber::kSize, allocation,
                                                 map, kDoubleUnaligned);
  return handle(HeapNumber::cast(result), isolate());
}

template V8_EXPORT_PRIVATE Handle<HeapNumber>
FactoryBase<Factory>::NewHeapNumber<AllocationType::kYoung>();
template V8_EXPORT_PRIVATE Handle<HeapNumber>
FactoryBase<Factory>::NewHeapNumber<AllocationType::kOld>();
template V8_EXPORT_PRIVATE Handle<HeapNumber>
FactoryBase<Factory>::NewHeapNumber<AllocationType::kReadOnly>();

template V8_EXPORT_PRIVATE Handle<HeapNumber>
FactoryBase<LocalFactory>::NewHeapNumber<AllocationType::kOld>();

template <typename Impl>
Handle<Struct> FactoryBase<Impl>::NewStruct(InstanceType type,
                                            AllocationType allocation) {
  Map map = Map::GetInstanceTypeMap(read_only_roots(), type);
  int size = map.instance_size();
  HeapObject result = AllocateRawWithImmortalMap(size, allocation, map);
  Handle<Struct> str = handle(Struct::cast(result), isolate());
  str->InitializeBody(size);
  return str;
}

template <typename Impl>
Handle<AccessorPair> FactoryBase<Impl>::NewAccessorPair() {
  Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(
      NewStruct(ACCESSOR_PAIR_TYPE, AllocationType::kOld));
  accessors->set_getter(read_only_roots().null_value(), SKIP_WRITE_BARRIER);
  accessors->set_setter(read_only_roots().null_value(), SKIP_WRITE_BARRIER);
  return accessors;
}

template <typename Impl>
Handle<FixedArray> FactoryBase<Impl>::NewFixedArray(int length,
                                                    AllocationType allocation) {
  DCHECK_LE(0, length);
  if (length == 0) return impl()->empty_fixed_array();
  return NewFixedArrayWithFiller(
      read_only_roots().fixed_array_map_handle(), length,
      read_only_roots().undefined_value_handle(), allocation);
}

template <typename Impl>
Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithMap(
    Handle<Map> map, int length, AllocationType allocation) {
  // Zero-length case must be handled outside, where the knowledge about
  // the map is.
  DCHECK_LT(0, length);
  return NewFixedArrayWithFiller(
      map, length, read_only_roots().undefined_value_handle(), allocation);
}

template <typename Impl>
Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithHoles(
    int length, AllocationType allocation) {
  DCHECK_LE(0, length);
  if (length == 0) return impl()->empty_fixed_array();
  return NewFixedArrayWithFiller(
      read_only_roots().fixed_array_map_handle(), length,
      read_only_roots().the_hole_value_handle(), allocation);
}

template <typename Impl>
Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithFiller(
    Handle<Map> map, int length, Handle<Oddball> filler,
    AllocationType allocation) {
  HeapObject result = AllocateRawFixedArray(length, allocation);
  DCHECK(ReadOnlyHeap::Contains(*map));
  DCHECK(ReadOnlyHeap::Contains(*filler));
  result.set_map_after_allocation(*map, SKIP_WRITE_BARRIER);
  Handle<FixedArray> array = handle(FixedArray::cast(result), isolate());
  array->set_length(length);
  MemsetTagged(array->data_start(), *filler, length);
  return array;
}

template <typename Impl>
Handle<FixedArrayBase> FactoryBase<Impl>::NewFixedDoubleArray(
    int length, AllocationType allocation) {
  if (length == 0) return impl()->empty_fixed_array();
  if (length < 0 || length > FixedDoubleArray::kMaxLength) {
    isolate()->FatalProcessOutOfHeapMemory("invalid array length");
  }
  int size = FixedDoubleArray::SizeFor(length);
  Map map = read_only_roots().fixed_double_array_map();
  HeapObject result =
      AllocateRawWithImmortalMap(size, allocation, map, kDoubleAligned);
  Handle<FixedDoubleArray> array =
      handle(FixedDoubleArray::cast(result), isolate());
  array->set_length(length);
  return array;
}

template <typename Impl>
Handle<WeakFixedArray> FactoryBase<Impl>::NewWeakFixedArrayWithMap(
    Map map, int length, AllocationType allocation) {
  // Zero-length case must be handled outside.
  DCHECK_LT(0, length);
  DCHECK(ReadOnlyHeap::Contains(map));

  HeapObject result =
      AllocateRawArray(WeakFixedArray::SizeFor(length), allocation);
  result.set_map_after_allocation(map, SKIP_WRITE_BARRIER);

  Handle<WeakFixedArray> array =
      handle(WeakFixedArray::cast(result), isolate());
  array->set_length(length);
  MemsetTagged(ObjectSlot(array->data_start()),
               read_only_roots().undefined_value(), length);

  return array;
}

template <typename Impl>
Handle<WeakFixedArray> FactoryBase<Impl>::NewWeakFixedArray(
    int length, AllocationType allocation) {
  DCHECK_LE(0, length);
  if (length == 0) return impl()->empty_weak_fixed_array();
  return NewWeakFixedArrayWithMap(read_only_roots().weak_fixed_array_map(),
                                  length, allocation);
}

template <typename Impl>
Handle<ByteArray> FactoryBase<Impl>::NewByteArray(int length,
                                                  AllocationType allocation) {
  if (length < 0 || length > ByteArray::kMaxLength) {
    isolate()->FatalProcessOutOfHeapMemory("invalid array length");
  }
  int size = ByteArray::SizeFor(length);
  HeapObject result = AllocateRawWithImmortalMap(
      size, allocation, read_only_roots().byte_array_map());
  Handle<ByteArray> array(ByteArray::cast(result), isolate());
  array->set_length(length);
  array->clear_padding();
  return array;
}

template <typename Impl>
Handle<BytecodeArray> FactoryBase<Impl>::NewBytecodeArray(
    int length, const byte* raw_bytecodes, int frame_size, int parameter_count,
    Handle<FixedArray> constant_pool) {
  if (length < 0 || length > BytecodeArray::kMaxLength) {
    isolate()->FatalProcessOutOfHeapMemory("invalid array length");
  }
  // Bytecode array is AllocationType::kOld, so constant pool array should be
  // too.
  DCHECK(!Heap::InYoungGeneration(*constant_pool));

  int size = BytecodeArray::SizeFor(length);
  HeapObject result = AllocateRawWithImmortalMap(
      size, AllocationType::kOld, read_only_roots().bytecode_array_map());
  Handle<BytecodeArray> instance(BytecodeArray::cast(result), isolate());
  instance->set_length(length);
  instance->set_frame_size(frame_size);
  instance->set_parameter_count(parameter_count);
  instance->set_incoming_new_target_or_generator_register(
      interpreter::Register::invalid_value());
  instance->set_osr_loop_nesting_level(0);
  instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge);
  instance->set_constant_pool(*constant_pool);
  instance->set_handler_table(read_only_roots().empty_byte_array());
  instance->set_source_position_table(read_only_roots().undefined_value(),
                                      kReleaseStore);
  CopyBytes(reinterpret_cast<byte*>(instance->GetFirstBytecodeAddress()),
            raw_bytecodes, length);
  instance->clear_padding();

  return instance;
}

template <typename Impl>
Handle<Script> FactoryBase<Impl>::NewScript(Handle<String> source) {
  return NewScriptWithId(source, isolate()->GetNextScriptId());
}

template <typename Impl>
Handle<Script> FactoryBase<Impl>::NewScriptWithId(Handle<String> source,
                                                  int script_id) {
  // Create and initialize script object.
  ReadOnlyRoots roots = read_only_roots();
  Handle<Script> script =
      Handle<Script>::cast(NewStruct(SCRIPT_TYPE, AllocationType::kOld));
  script->set_source(*source);
  script->set_name(roots.undefined_value());
  script->set_id(script_id);
  script->set_line_offset(0);
  script->set_column_offset(0);
  script->set_context_data(roots.undefined_value());
  script->set_type(Script::TYPE_NORMAL);
  script->set_line_ends(roots.undefined_value());
  script->set_eval_from_shared_or_wrapped_arguments(roots.undefined_value());
  script->set_eval_from_position(0);
  script->set_shared_function_infos(roots.empty_weak_fixed_array(),
                                    SKIP_WRITE_BARRIER);
  script->set_flags(0);
  script->set_host_defined_options(roots.empty_fixed_array());

  if (script_id != Script::kTemporaryScriptId) {
    impl()->AddToScriptList(script);
  }

  LOG(isolate(), ScriptEvent(Logger::ScriptEventType::kCreate, script_id));
  return script;
}

template <typename Impl>
Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfoForLiteral(
    FunctionLiteral* literal, Handle<Script> script, bool is_toplevel) {
  FunctionKind kind = literal->kind();
  Handle<SharedFunctionInfo> shared =
      NewSharedFunctionInfo(literal->GetName(isolate()), MaybeHandle<Code>(),
                            Builtins::kCompileLazy, kind);
  SharedFunctionInfo::InitFromFunctionLiteral(isolate(), shared, literal,
                                              is_toplevel);
  shared->SetScript(read_only_roots(), *script, literal->function_literal_id(),
                    false);
  return shared;
}

template <typename Impl>
Handle<PreparseData> FactoryBase<Impl>::NewPreparseData(int data_length,
                                                        int children_length) {
  int size = PreparseData::SizeFor(data_length, children_length);
  Handle<PreparseData> result = handle(
      PreparseData::cast(AllocateRawWithImmortalMap(
          size, AllocationType::kOld, read_only_roots().preparse_data_map())),
      isolate());
  result->set_data_length(data_length);
  result->set_children_length(children_length);
  MemsetTagged(result->inner_data_start(), read_only_roots().null_value(),
               children_length);
  result->clear_padding();
  return result;
}

template <typename Impl>
Handle<UncompiledDataWithoutPreparseData>
FactoryBase<Impl>::NewUncompiledDataWithoutPreparseData(
    Handle<String> inferred_name, int32_t start_position,
    int32_t end_position) {
  Handle<UncompiledDataWithoutPreparseData> result = handle(
      UncompiledDataWithoutPreparseData::cast(NewWithImmortalMap(
          impl()->read_only_roots().uncompiled_data_without_preparse_data_map(),
          AllocationType::kOld)),
      isolate());

  result->Init(impl(), *inferred_name, start_position, end_position);
  return result;
}

template <typename Impl>
Handle<UncompiledDataWithPreparseData>
FactoryBase<Impl>::NewUncompiledDataWithPreparseData(
    Handle<String> inferred_name, int32_t start_position, int32_t end_position,
    Handle<PreparseData> preparse_data) {
  Handle<UncompiledDataWithPreparseData> result = handle(
      UncompiledDataWithPreparseData::cast(NewWithImmortalMap(
          impl()->read_only_roots().uncompiled_data_with_preparse_data_map(),
          AllocationType::kOld)),
      isolate());

  result->Init(impl(), *inferred_name, start_position, end_position,
               *preparse_data);

  return result;
}

template <typename Impl>
Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfo(
    MaybeHandle<String> maybe_name, MaybeHandle<HeapObject> maybe_function_data,
    int maybe_builtin_index, FunctionKind kind) {
  Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo();

  // Function names are assumed to be flat elsewhere.
  Handle<String> shared_name;
  bool has_shared_name = maybe_name.ToHandle(&shared_name);
  if (has_shared_name) {
    DCHECK(shared_name->IsFlat());
    shared->set_name_or_scope_info(*shared_name, kReleaseStore);
  } else {
    DCHECK_EQ(shared->name_or_scope_info(kAcquireLoad),
              SharedFunctionInfo::kNoSharedNameSentinel);
  }

  Handle<HeapObject> function_data;
  if (maybe_function_data.ToHandle(&function_data)) {
    // If we pass function_data then we shouldn't pass a builtin index, and
    // the function_data should not be code with a builtin.
    DCHECK(!Builtins::IsBuiltinId(maybe_builtin_index));
    DCHECK_IMPLIES(function_data->IsCode(),
                   !Code::cast(*function_data).is_builtin());
    shared->set_function_data(*function_data, kReleaseStore);
  } else if (Builtins::IsBuiltinId(maybe_builtin_index)) {
    shared->set_builtin_id(maybe_builtin_index);
  } else {
    DCHECK(shared->HasBuiltinId());
    DCHECK_EQ(Builtins::kIllegal, shared->builtin_id());
  }

  shared->CalculateConstructAsBuiltin();
  shared->set_kind(kind);

#ifdef VERIFY_HEAP
  if (FLAG_verify_heap) shared->SharedFunctionInfoVerify(isolate());
#endif  // VERIFY_HEAP
  return shared;
}

template <typename Impl>
Handle<ObjectBoilerplateDescription>
FactoryBase<Impl>::NewObjectBoilerplateDescription(int boilerplate,
                                                   int all_properties,
                                                   int index_keys,
                                                   bool has_seen_proto) {
  DCHECK_GE(boilerplate, 0);
  DCHECK_GE(all_properties, index_keys);
  DCHECK_GE(index_keys, 0);

  int backing_store_size =
      all_properties - index_keys - (has_seen_proto ? 1 : 0);
  DCHECK_GE(backing_store_size, 0);
  bool has_different_size_backing_store = boilerplate != backing_store_size;

  // Space for name and value for every boilerplate property + LiteralType flag.
  int size =
      2 * boilerplate + ObjectBoilerplateDescription::kDescriptionStartIndex;

  if (has_different_size_backing_store) {
    // An extra entry for the backing store size.
    size++;
  }

  Handle<ObjectBoilerplateDescription> description =
      Handle<ObjectBoilerplateDescription>::cast(NewFixedArrayWithMap(
          read_only_roots().object_boilerplate_description_map_handle(), size,
          AllocationType::kOld));

  if (has_different_size_backing_store) {
    DCHECK_IMPLIES((boilerplate == (all_properties - index_keys)),
                   has_seen_proto);
    description->set_backing_store_size(backing_store_size);
  }

  description->set_flags(0);

  return description;
}

template <typename Impl>
Handle<ArrayBoilerplateDescription>
FactoryBase<Impl>::NewArrayBoilerplateDescription(
    ElementsKind elements_kind, Handle<FixedArrayBase> constant_values) {
  Handle<ArrayBoilerplateDescription> result =
      Handle<ArrayBoilerplateDescription>::cast(
          NewStruct(ARRAY_BOILERPLATE_DESCRIPTION_TYPE, AllocationType::kOld));
  result->set_elements_kind(elements_kind);
  result->set_constant_elements(*constant_values);
  return result;
}

template <typename Impl>
Handle<TemplateObjectDescription>
FactoryBase<Impl>::NewTemplateObjectDescription(
    Handle<FixedArray> raw_strings, Handle<FixedArray> cooked_strings) {
  DCHECK_EQ(raw_strings->length(), cooked_strings->length());
  DCHECK_LT(0, raw_strings->length());
  Handle<TemplateObjectDescription> result =
      Handle<TemplateObjectDescription>::cast(
          NewStruct(TEMPLATE_OBJECT_DESCRIPTION_TYPE, AllocationType::kOld));
  result->set_raw_strings(*raw_strings);
  result->set_cooked_strings(*cooked_strings);
  return result;
}

template <typename Impl>
Handle<FeedbackMetadata> FactoryBase<Impl>::NewFeedbackMetadata(
    int slot_count, int create_closure_slot_count, AllocationType allocation) {
  DCHECK_LE(0, slot_count);
  int size = FeedbackMetadata::SizeFor(slot_count);
  HeapObject result = AllocateRawWithImmortalMap(
      size, allocation, read_only_roots().feedback_metadata_map());
  Handle<FeedbackMetadata> data(FeedbackMetadata::cast(result), isolate());
  data->set_slot_count(slot_count);
  data->set_create_closure_slot_count(create_closure_slot_count);

  // Initialize the data section to 0.
  int data_size = size - FeedbackMetadata::kHeaderSize;
  Address data_start = data->address() + FeedbackMetadata::kHeaderSize;
  memset(reinterpret_cast<byte*>(data_start), 0, data_size);
  // Fields have been zeroed out but not initialized, so this object will not
  // pass object verification at this point.
  return data;
}

template <typename Impl>
Handle<CoverageInfo> FactoryBase<Impl>::NewCoverageInfo(
    const ZoneVector<SourceRange>& slots) {
  const int slot_count = static_cast<int>(slots.size());

  int size = CoverageInfo::SizeFor(slot_count);
  Map map = read_only_roots().coverage_info_map();
  HeapObject result =
      AllocateRawWithImmortalMap(size, AllocationType::kOld, map);
  Handle<CoverageInfo> info(CoverageInfo::cast(result), isolate());

  info->set_slot_count(slot_count);
  for (int i = 0; i < slot_count; i++) {
    SourceRange range = slots[i];
    info->InitializeSlot(i, range.start, range.end);
  }

  return info;
}

template <typename Impl>
Handle<String> FactoryBase<Impl>::MakeOrFindTwoCharacterString(uint16_t c1,
                                                               uint16_t c2) {
  if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
    uint8_t buffer[] = {static_cast<uint8_t>(c1), static_cast<uint8_t>(c2)};
    return InternalizeString(Vector<const uint8_t>(buffer, 2));
  }
  uint16_t buffer[] = {c1, c2};
  return InternalizeString(Vector<const uint16_t>(buffer, 2));
}

template <typename Impl>
template <class StringTableKey>
Handle<String> FactoryBase<Impl>::InternalizeStringWithKey(
    StringTableKey* key) {
  return isolate()->string_table()->LookupKey(isolate(), key);
}

template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
        OneByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
        TwoByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
        SeqOneByteSubStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
        SeqTwoByteSubStringKey* key);

template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<String> FactoryBase<LocalFactory>::InternalizeStringWithKey(
        OneByteStringKey* key);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    Handle<String> FactoryBase<LocalFactory>::InternalizeStringWithKey(
        TwoByteStringKey* key);

template <typename Impl>
Handle<String> FactoryBase<Impl>::InternalizeString(
    const Vector<const uint8_t>& string, bool convert_encoding) {
  SequentialStringKey<uint8_t> key(string, HashSeed(read_only_roots()),
                                   convert_encoding);
  return InternalizeStringWithKey(&key);
}

template <typename Impl>
Handle<String> FactoryBase<Impl>::InternalizeString(
    const Vector<const uint16_t>& string, bool convert_encoding) {
  SequentialStringKey<uint16_t> key(string, HashSeed(read_only_roots()),
                                    convert_encoding);
  return InternalizeStringWithKey(&key);
}

template <typename Impl>
Handle<SeqOneByteString> FactoryBase<Impl>::NewOneByteInternalizedString(
    const Vector<const uint8_t>& str, uint32_t hash_field) {
  Handle<SeqOneByteString> result =
      AllocateRawOneByteInternalizedString(str.length(), hash_field);
  DisallowHeapAllocation no_gc;
  MemCopy(result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()),
          str.begin(), str.length());
  return result;
}

template <typename Impl>
Handle<SeqTwoByteString> FactoryBase<Impl>::NewTwoByteInternalizedString(
    const Vector<const uc16>& str, uint32_t hash_field) {
  Handle<SeqTwoByteString> result =
      AllocateRawTwoByteInternalizedString(str.length(), hash_field);
  DisallowHeapAllocation no_gc;
  MemCopy(result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()),
          str.begin(), str.length() * kUC16Size);
  return result;
}

template <typename Impl>
MaybeHandle<SeqOneByteString> FactoryBase<Impl>::NewRawOneByteString(
    int length, AllocationType allocation) {
  if (length > String::kMaxLength || length < 0) {
    THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqOneByteString);
  }
  DCHECK_GT(length, 0);  // Use Factory::empty_string() instead.
  int size = SeqOneByteString::SizeFor(length);
  DCHECK_GE(SeqOneByteString::kMaxSize, size);

  HeapObject result = AllocateRawWithImmortalMap(
      size, allocation, read_only_roots().one_byte_string_map());
  Handle<SeqOneByteString> string =
      handle(SeqOneByteString::cast(result), isolate());
  string->set_length(length);
  string->set_hash_field(String::kEmptyHashField);
  DCHECK_EQ(size, string->Size());
  return string;
}

template <typename Impl>
MaybeHandle<SeqTwoByteString> FactoryBase<Impl>::NewRawTwoByteString(
    int length, AllocationType allocation) {
  if (length > String::kMaxLength || length < 0) {
    THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqTwoByteString);
  }
  DCHECK_GT(length, 0);  // Use Factory::empty_string() instead.
  int size = SeqTwoByteString::SizeFor(length);
  DCHECK_GE(SeqTwoByteString::kMaxSize, size);

  HeapObject result = AllocateRawWithImmortalMap(
      size, allocation, read_only_roots().string_map());
  Handle<SeqTwoByteString> string =
      handle(SeqTwoByteString::cast(result), isolate());
  string->set_length(length);
  string->set_hash_field(String::kEmptyHashField);
  DCHECK_EQ(size, string->Size());
  return string;
}

template <typename Impl>
MaybeHandle<String> FactoryBase<Impl>::NewConsString(
    Handle<String> left, Handle<String> right, AllocationType allocation) {
  if (left->IsThinString()) {
    left = handle(ThinString::cast(*left).actual(), isolate());
  }
  if (right->IsThinString()) {
    right = handle(ThinString::cast(*right).actual(), isolate());
  }
  int left_length = left->length();
  if (left_length == 0) return right;
  int right_length = right->length();
  if (right_length == 0) return left;

  int length = left_length + right_length;

  if (length == 2) {
    uint16_t c1 = left->Get(0);
    uint16_t c2 = right->Get(0);
    return MakeOrFindTwoCharacterString(c1, c2);
  }

  // Make sure that an out of memory exception is thrown if the length
  // of the new cons string is too large.
  if (length > String::kMaxLength || length < 0) {
    THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
  }

  bool left_is_one_byte = left->IsOneByteRepresentation();
  bool right_is_one_byte = right->IsOneByteRepresentation();
  bool is_one_byte = left_is_one_byte && right_is_one_byte;

  // If the resulting string is small make a flat string.
  if (length < ConsString::kMinLength) {
    // Note that neither of the two inputs can be a slice because:
    STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
    DCHECK(left->IsFlat());
    DCHECK(right->IsFlat());

    STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
    if (is_one_byte) {
      Handle<SeqOneByteString> result =
          NewRawOneByteString(length, allocation).ToHandleChecked();
      DisallowHeapAllocation no_gc;
      uint8_t* dest =
          result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded());
      // Copy left part.
      {
        SharedStringAccessGuardIfNeeded access_guard(*left);
        const uint8_t* src =
            left->template GetChars<uint8_t>(no_gc, access_guard);
        CopyChars(dest, src, left_length);
      }
      // Copy right part.
      {
        SharedStringAccessGuardIfNeeded access_guard(*right);
        const uint8_t* src =
            right->template GetChars<uint8_t>(no_gc, access_guard);
        CopyChars(dest + left_length, src, right_length);
      }
      return result;
    }

    Handle<SeqTwoByteString> result =
        NewRawTwoByteString(length, allocation).ToHandleChecked();

    DisallowHeapAllocation no_gc;
    uc16* sink =
        result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded());
    String::WriteToFlat(*left, sink, 0, left->length());
    String::WriteToFlat(*right, sink + left->length(), 0, right->length());
    return result;
  }

  return NewConsString(left, right, length, is_one_byte, allocation);
}

template <typename Impl>
Handle<String> FactoryBase<Impl>::NewConsString(Handle<String> left,
                                                Handle<String> right,
                                                int length, bool one_byte,
                                                AllocationType allocation) {
  DCHECK(!left->IsThinString());
  DCHECK(!right->IsThinString());
  DCHECK_GE(length, ConsString::kMinLength);
  DCHECK_LE(length, String::kMaxLength);

  Handle<ConsString> result = handle(
      ConsString::cast(
          one_byte
              ? NewWithImmortalMap(read_only_roots().cons_one_byte_string_map(),
                                   allocation)
              : NewWithImmortalMap(read_only_roots().cons_string_map(),
                                   allocation)),
      isolate());

  DisallowHeapAllocation no_gc;
  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);

  result->set_hash_field(String::kEmptyHashField);
  result->set_length(length);
  result->set_first(*left, mode);
  result->set_second(*right, mode);
  return result;
}

template <typename Impl>
Handle<FreshlyAllocatedBigInt> FactoryBase<Impl>::NewBigInt(
    int length, AllocationType allocation) {
  if (length < 0 || length > BigInt::kMaxLength) {
    isolate()->FatalProcessOutOfHeapMemory("invalid BigInt length");
  }
  HeapObject result = AllocateRawWithImmortalMap(
      BigInt::SizeFor(length), allocation, read_only_roots().bigint_map());
  FreshlyAllocatedBigInt bigint = FreshlyAllocatedBigInt::cast(result);
  bigint.clear_padding();
  return handle(bigint, isolate());
}

template <typename Impl>
Handle<ScopeInfo> FactoryBase<Impl>::NewScopeInfo(int length,
                                                  AllocationType type) {
  DCHECK(type == AllocationType::kOld || type == AllocationType::kReadOnly);
  return Handle<ScopeInfo>::cast(NewFixedArrayWithMap(
      read_only_roots().scope_info_map_handle(), length, type));
}

template <typename Impl>
Handle<SourceTextModuleInfo> FactoryBase<Impl>::NewSourceTextModuleInfo() {
  return Handle<SourceTextModuleInfo>::cast(NewFixedArrayWithMap(
      read_only_roots().module_info_map_handle(), SourceTextModuleInfo::kLength,
      AllocationType::kOld));
}

template <typename Impl>
Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfo() {
  Map map = read_only_roots().shared_function_info_map();

  Handle<SharedFunctionInfo> shared = handle(
      SharedFunctionInfo::cast(NewWithImmortalMap(map, AllocationType::kOld)),
      isolate());
  int unique_id = -1;
#if V8_SFI_HAS_UNIQUE_ID
  unique_id = isolate()->GetNextUniqueSharedFunctionInfoId();
#endif  // V8_SFI_HAS_UNIQUE_ID

  shared->Init(read_only_roots(), unique_id);

#ifdef VERIFY_HEAP
  if (FLAG_verify_heap) shared->SharedFunctionInfoVerify(isolate());
#endif  // VERIFY_HEAP
  return shared;
}

template <typename Impl>
Handle<DescriptorArray> FactoryBase<Impl>::NewDescriptorArray(
    int number_of_descriptors, int slack, AllocationType allocation) {
  int number_of_all_descriptors = number_of_descriptors + slack;
  // Zero-length case must be handled outside.
  DCHECK_LT(0, number_of_all_descriptors);
  int size = DescriptorArray::SizeFor(number_of_all_descriptors);
  HeapObject obj = AllocateRawWithImmortalMap(
      size, allocation, read_only_roots().descriptor_array_map());
  DescriptorArray array = DescriptorArray::cast(obj);
  array.Initialize(read_only_roots().empty_enum_cache(),
                   read_only_roots().undefined_value(), number_of_descriptors,
                   slack);
  return handle(array, isolate());
}

template <typename Impl>
Handle<ClassPositions> FactoryBase<Impl>::NewClassPositions(int start,
                                                            int end) {
  Handle<ClassPositions> class_positions = Handle<ClassPositions>::cast(
      NewStruct(CLASS_POSITIONS_TYPE, AllocationType::kOld));
  class_positions->set_start(start);
  class_positions->set_end(end);
  return class_positions;
}

template <typename Impl>
Handle<SeqOneByteString>
FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length,
                                                        uint32_t hash_field) {
  CHECK_GE(String::kMaxLength, length);
  // The canonical empty_string is the only zero-length string we allow.
  DCHECK_IMPLIES(length == 0, !impl()->EmptyStringRootIsInitialized());

  Map map = read_only_roots().one_byte_internalized_string_map();
  int size = SeqOneByteString::SizeFor(length);
  HeapObject result = AllocateRawWithImmortalMap(
      size,
      impl()->CanAllocateInReadOnlySpace() ? AllocationType::kReadOnly
                                           : AllocationType::kOld,
      map);
  Handle<SeqOneByteString> answer =
      handle(SeqOneByteString::cast(result), isolate());
  answer->set_length(length);
  answer->set_hash_field(hash_field);
  DCHECK_EQ(size, answer->Size());
  return answer;
}

template <typename Impl>
Handle<SeqTwoByteString>
FactoryBase<Impl>::AllocateRawTwoByteInternalizedString(int length,
                                                        uint32_t hash_field) {
  CHECK_GE(String::kMaxLength, length);
  DCHECK_NE(0, length);  // Use Heap::empty_string() instead.

  Map map = read_only_roots().internalized_string_map();
  int size = SeqTwoByteString::SizeFor(length);
  HeapObject result =
      AllocateRawWithImmortalMap(size, AllocationType::kOld, map);
  Handle<SeqTwoByteString> answer =
      handle(SeqTwoByteString::cast(result), isolate());
  answer->set_length(length);
  answer->set_hash_field(hash_field);
  DCHECK_EQ(size, result.Size());
  return answer;
}

template <typename Impl>
HeapObject FactoryBase<Impl>::AllocateRawArray(int size,
                                               AllocationType allocation) {
  HeapObject result = AllocateRaw(size, allocation);
  if (!V8_ENABLE_THIRD_PARTY_HEAP_BOOL &&
      (size > Heap::MaxRegularHeapObjectSize(allocation)) &&
      FLAG_use_marking_progress_bar) {
    BasicMemoryChunk* chunk = BasicMemoryChunk::FromHeapObject(result);
    chunk->SetFlag<AccessMode::ATOMIC>(MemoryChunk::HAS_PROGRESS_BAR);
  }
  return result;
}

template <typename Impl>
HeapObject FactoryBase<Impl>::AllocateRawFixedArray(int length,
                                                    AllocationType allocation) {
  if (length < 0 || length > FixedArray::kMaxLength) {
    isolate()->FatalProcessOutOfHeapMemory("invalid array length");
  }
  return AllocateRawArray(FixedArray::SizeFor(length), allocation);
}

template <typename Impl>
HeapObject FactoryBase<Impl>::AllocateRawWeakArrayList(
    int capacity, AllocationType allocation) {
  if (capacity < 0 || capacity > WeakArrayList::kMaxCapacity) {
    isolate()->FatalProcessOutOfHeapMemory("invalid array length");
  }
  return AllocateRawArray(WeakArrayList::SizeForCapacity(capacity), allocation);
}

template <typename Impl>
HeapObject FactoryBase<Impl>::NewWithImmortalMap(Map map,
                                                 AllocationType allocation) {
  return AllocateRawWithImmortalMap(map.instance_size(), allocation, map);
}

template <typename Impl>
HeapObject FactoryBase<Impl>::AllocateRawWithImmortalMap(
    int size, AllocationType allocation, Map map,
    AllocationAlignment alignment) {
  // TODO(delphick): Potentially you could also pass a immortal immovable Map
  // from MAP_SPACE here, like external_map or message_object_map, but currently
  // noone does so this check is sufficient.
  DCHECK(ReadOnlyHeap::Contains(map));
  HeapObject result = AllocateRaw(size, allocation, alignment);
  result.set_map_after_allocation(map, SKIP_WRITE_BARRIER);
  return result;
}

template <typename Impl>
HeapObject FactoryBase<Impl>::AllocateRaw(int size, AllocationType allocation,
                                          AllocationAlignment alignment) {
  return impl()->AllocateRaw(size, allocation, alignment);
}

// Instantiate FactoryBase for the two variants we want.
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) FactoryBase<Factory>;
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    FactoryBase<LocalFactory>;

}  // namespace internal
}  // namespace v8
