// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/builtins/builtins-constructor-gen.h"

#include "src/ast/ast.h"
#include "src/builtins/builtins-call-gen.h"
#include "src/builtins/builtins-constructor.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/macro-assembler.h"
#include "src/logging/counters.h"
#include "src/objects/objects-inl.h"

namespace v8 {
namespace internal {

void Builtins::Generate_ConstructVarargs(MacroAssembler* masm) {
  Generate_CallOrConstructVarargs(masm,
                                  BUILTIN_CODE(masm->isolate(), Construct));
}

void Builtins::Generate_ConstructForwardVarargs(MacroAssembler* masm) {
  Generate_CallOrConstructForwardVarargs(
      masm, CallOrConstructMode::kConstruct,
      BUILTIN_CODE(masm->isolate(), Construct));
}

void Builtins::Generate_ConstructFunctionForwardVarargs(MacroAssembler* masm) {
  Generate_CallOrConstructForwardVarargs(
      masm, CallOrConstructMode::kConstruct,
      BUILTIN_CODE(masm->isolate(), ConstructFunction));
}

TF_BUILTIN(ConstructWithArrayLike, CallOrConstructBuiltinsAssembler) {
  TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
  SloppyTNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
  TNode<Object> arguments_list = CAST(Parameter(Descriptor::kArgumentsList));
  TNode<Context> context = CAST(Parameter(Descriptor::kContext));
  CallOrConstructWithArrayLike(target, new_target, arguments_list, context);
}

TF_BUILTIN(ConstructWithSpread, CallOrConstructBuiltinsAssembler) {
  TNode<Object> target = CAST(Parameter(Descriptor::kTarget));
  SloppyTNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
  TNode<Object> spread = CAST(Parameter(Descriptor::kSpread));
  TNode<Int32T> args_count =
      UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
  TNode<Context> context = CAST(Parameter(Descriptor::kContext));
  CallOrConstructWithSpread(target, new_target, spread, args_count, context);
}

using Node = compiler::Node;

TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) {
  Node* shared_function_info = Parameter(Descriptor::kSharedFunctionInfo);
  Node* feedback_cell = Parameter(Descriptor::kFeedbackCell);
  Node* context = Parameter(Descriptor::kContext);

  CSA_ASSERT(this, IsFeedbackCell(feedback_cell));
  CSA_ASSERT(this, IsSharedFunctionInfo(shared_function_info));

  IncrementCounter(isolate()->counters()->fast_new_closure_total(), 1);

  // Bump the closure counter encoded the {feedback_cell}s map.
  {
    Node* const feedback_cell_map = LoadMap(feedback_cell);
    Label no_closures(this), one_closure(this), cell_done(this);

    GotoIf(IsNoClosuresCellMap(feedback_cell_map), &no_closures);
    GotoIf(IsOneClosureCellMap(feedback_cell_map), &one_closure);
    CSA_ASSERT(this, IsManyClosuresCellMap(feedback_cell_map),
               feedback_cell_map, feedback_cell);
    Goto(&cell_done);

    BIND(&no_closures);
    StoreMapNoWriteBarrier(feedback_cell, RootIndex::kOneClosureCellMap);
    Goto(&cell_done);

    BIND(&one_closure);
    StoreMapNoWriteBarrier(feedback_cell, RootIndex::kManyClosuresCellMap);
    Goto(&cell_done);

    BIND(&cell_done);
  }

  // The calculation of |function_map_index| must be in sync with
  // SharedFunctionInfo::function_map_index().
  Node* const flags =
      LoadObjectField(shared_function_info, SharedFunctionInfo::kFlagsOffset,
                      MachineType::Uint32());
  Node* const function_map_index = IntPtrAdd(
      DecodeWordFromWord32<SharedFunctionInfo::FunctionMapIndexBits>(flags),
      IntPtrConstant(Context::FIRST_FUNCTION_MAP_INDEX));
  CSA_ASSERT(this, UintPtrLessThanOrEqual(
                       function_map_index,
                       IntPtrConstant(Context::LAST_FUNCTION_MAP_INDEX)));

  // Get the function map in the current native context and set that
  // as the map of the allocated object.
  Node* const native_context = LoadNativeContext(context);
  Node* const function_map =
      LoadContextElement(native_context, function_map_index);

  // Create a new closure from the given function info in new space
  TNode<IntPtrT> instance_size_in_bytes =
      TimesTaggedSize(LoadMapInstanceSizeInWords(function_map));
  TNode<Object> result = Allocate(instance_size_in_bytes);
  StoreMapNoWriteBarrier(result, function_map);
  InitializeJSObjectBodyNoSlackTracking(result, function_map,
                                        instance_size_in_bytes,
                                        JSFunction::kSizeWithoutPrototype);

  // Initialize the rest of the function.
  StoreObjectFieldRoot(result, JSObject::kPropertiesOrHashOffset,
                       RootIndex::kEmptyFixedArray);
  StoreObjectFieldRoot(result, JSObject::kElementsOffset,
                       RootIndex::kEmptyFixedArray);
  {
    // Set function prototype if necessary.
    Label done(this), init_prototype(this);
    Branch(IsFunctionWithPrototypeSlotMap(function_map), &init_prototype,
           &done);

    BIND(&init_prototype);
    StoreObjectFieldRoot(result, JSFunction::kPrototypeOrInitialMapOffset,
                         RootIndex::kTheHoleValue);
    Goto(&done);
    BIND(&done);
  }

  STATIC_ASSERT(JSFunction::kSizeWithoutPrototype == 7 * kTaggedSize);
  StoreObjectFieldNoWriteBarrier(result, JSFunction::kFeedbackCellOffset,
                                 feedback_cell);
  StoreObjectFieldNoWriteBarrier(result, JSFunction::kSharedFunctionInfoOffset,
                                 shared_function_info);
  StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, context);
  Handle<Code> lazy_builtin_handle =
      isolate()->builtins()->builtin_handle(Builtins::kCompileLazy);
  Node* lazy_builtin = HeapConstant(lazy_builtin_handle);
  StoreObjectFieldNoWriteBarrier(result, JSFunction::kCodeOffset, lazy_builtin);
  Return(result);
}

TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
  TNode<Context> context = CAST(Parameter(Descriptor::kContext));
  TNode<JSFunction> target = CAST(Parameter(Descriptor::kTarget));
  TNode<JSReceiver> new_target = CAST(Parameter(Descriptor::kNewTarget));

  Label call_runtime(this);

  TNode<JSObject> result =
      EmitFastNewObject(context, target, new_target, &call_runtime);
  Return(result);

  BIND(&call_runtime);
  TailCallRuntime(Runtime::kNewObject, context, target, new_target);
}

compiler::TNode<JSObject> ConstructorBuiltinsAssembler::EmitFastNewObject(
    SloppyTNode<Context> context, SloppyTNode<JSFunction> target,
    SloppyTNode<JSReceiver> new_target) {
  TVARIABLE(JSObject, var_obj);
  Label call_runtime(this), end(this);

  var_obj = EmitFastNewObject(context, target, new_target, &call_runtime);
  Goto(&end);

  BIND(&call_runtime);
  var_obj = CAST(CallRuntime(Runtime::kNewObject, context, target, new_target));
  Goto(&end);

  BIND(&end);
  return var_obj.value();
}

compiler::TNode<JSObject> ConstructorBuiltinsAssembler::EmitFastNewObject(
    SloppyTNode<Context> context, SloppyTNode<JSFunction> target,
    SloppyTNode<JSReceiver> new_target, Label* call_runtime) {
  // Verify that the new target is a JSFunction.
  Label fast(this), end(this);
  GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast);
  Goto(call_runtime);

  BIND(&fast);

  // Load the initial map and verify that it's in fact a map.
  Node* initial_map =
      LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset);
  GotoIf(TaggedIsSmi(initial_map), call_runtime);
  GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime);

  // Fall back to runtime if the target differs from the new target's
  // initial map constructor.
  Node* new_target_constructor =
      LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset);
  GotoIf(WordNotEqual(target, new_target_constructor), call_runtime);

  VARIABLE(properties, MachineRepresentation::kTagged);

  Label instantiate_map(this), allocate_properties(this);
  GotoIf(IsDictionaryMap(initial_map), &allocate_properties);
  {
    properties.Bind(EmptyFixedArrayConstant());
    Goto(&instantiate_map);
  }
  BIND(&allocate_properties);
  {
    properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
    Goto(&instantiate_map);
  }

  BIND(&instantiate_map);
  return AllocateJSObjectFromMap(initial_map, properties.value(), nullptr,
                                 kNone, kWithSlackTracking);
}

Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext(
    Node* scope_info, Node* slots_uint32, Node* context, ScopeType scope_type) {
  TNode<IntPtrT> slots = Signed(ChangeUint32ToWord(slots_uint32));
  TNode<IntPtrT> size = ElementOffsetFromIndex(
      slots, PACKED_ELEMENTS, INTPTR_PARAMETERS, Context::kTodoHeaderSize);

  // Create a new closure from the given function info in new space
  TNode<Context> function_context =
      UncheckedCast<Context>(AllocateInNewSpace(size));

  RootIndex context_type;
  switch (scope_type) {
    case EVAL_SCOPE:
      context_type = RootIndex::kEvalContextMap;
      break;
    case FUNCTION_SCOPE:
      context_type = RootIndex::kFunctionContextMap;
      break;
    default:
      UNREACHABLE();
  }
  // Set up the header.
  StoreMapNoWriteBarrier(function_context, context_type);
  TNode<IntPtrT> min_context_slots = IntPtrConstant(Context::MIN_CONTEXT_SLOTS);
  // TODO(ishell): for now, length also includes MIN_CONTEXT_SLOTS.
  TNode<IntPtrT> length = IntPtrAdd(slots, min_context_slots);
  StoreObjectFieldNoWriteBarrier(function_context, Context::kLengthOffset,
                                 SmiTag(length));
  StoreObjectFieldNoWriteBarrier(function_context, Context::kScopeInfoOffset,
                                 scope_info);
  StoreObjectFieldNoWriteBarrier(function_context, Context::kPreviousOffset,
                                 context);
  StoreObjectFieldNoWriteBarrier(function_context, Context::kExtensionOffset,
                                 TheHoleConstant());
  TNode<Context> native_context = LoadNativeContext(context);
  StoreObjectFieldNoWriteBarrier(function_context,
                                 Context::kNativeContextOffset, native_context);

  // Initialize the varrest of the slots to undefined.
  TNode<HeapObject> undefined = UndefinedConstant();
  TNode<IntPtrT> start_offset = IntPtrConstant(Context::kTodoHeaderSize);
  CodeStubAssembler::VariableList vars(0, zone());
  BuildFastLoop(
      vars, start_offset, size,
      [=](Node* offset) {
        StoreObjectFieldNoWriteBarrier(
            function_context, UncheckedCast<IntPtrT>(offset), undefined);
      },
      kTaggedSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
  return function_context;
}

TF_BUILTIN(FastNewFunctionContextEval, ConstructorBuiltinsAssembler) {
  Node* scope_info = Parameter(Descriptor::kScopeInfo);
  Node* slots = Parameter(Descriptor::kSlots);
  Node* context = Parameter(Descriptor::kContext);
  Return(EmitFastNewFunctionContext(scope_info, slots, context,
                                    ScopeType::EVAL_SCOPE));
}

TF_BUILTIN(FastNewFunctionContextFunction, ConstructorBuiltinsAssembler) {
  Node* scope_info = Parameter(Descriptor::kScopeInfo);
  Node* slots = Parameter(Descriptor::kSlots);
  Node* context = Parameter(Descriptor::kContext);
  Return(EmitFastNewFunctionContext(scope_info, slots, context,
                                    ScopeType::FUNCTION_SCOPE));
}

Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral(
    Node* feedback_vector, Node* slot, Node* pattern, Node* flags,
    Node* context) {
  Label call_runtime(this, Label::kDeferred), end(this);

  GotoIf(IsUndefined(feedback_vector), &call_runtime);

  VARIABLE(result, MachineRepresentation::kTagged);
  TNode<Object> literal_site =
      CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
  GotoIf(NotHasBoilerplate(literal_site), &call_runtime);
  {
    Node* boilerplate = literal_site;
    CSA_ASSERT(this, IsJSRegExp(boilerplate));
    int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kTaggedSize;
    Node* copy = Allocate(size);
    for (int offset = 0; offset < size; offset += kTaggedSize) {
      Node* value = LoadObjectField(boilerplate, offset);
      StoreObjectFieldNoWriteBarrier(copy, offset, value);
    }
    result.Bind(copy);
    Goto(&end);
  }

  BIND(&call_runtime);
  {
    result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context,
                            feedback_vector, SmiTag(slot), pattern, flags));
    Goto(&end);
  }

  BIND(&end);
  return result.value();
}

TF_BUILTIN(CreateRegExpLiteral, ConstructorBuiltinsAssembler) {
  Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
  Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
  Node* pattern = Parameter(Descriptor::kPattern);
  Node* flags = Parameter(Descriptor::kFlags);
  Node* context = Parameter(Descriptor::kContext);
  Node* result =
      EmitCreateRegExpLiteral(feedback_vector, slot, pattern, flags, context);
  Return(result);
}

Node* ConstructorBuiltinsAssembler::EmitCreateShallowArrayLiteral(
    Node* feedback_vector, Node* slot, Node* context, Label* call_runtime,
    AllocationSiteMode allocation_site_mode) {
  Label zero_capacity(this), cow_elements(this), fast_elements(this),
      return_result(this);
  VARIABLE(result, MachineRepresentation::kTagged);

  TNode<Object> maybe_allocation_site =
      CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
  GotoIf(NotHasBoilerplate(maybe_allocation_site), call_runtime);

  TNode<AllocationSite> allocation_site = CAST(maybe_allocation_site);
  TNode<JSArray> boilerplate = CAST(LoadBoilerplate(allocation_site));

  ParameterMode mode = OptimalParameterMode();
  if (allocation_site_mode == TRACK_ALLOCATION_SITE) {
    return CloneFastJSArray(context, boilerplate, mode, allocation_site);
  } else {
    return CloneFastJSArray(context, boilerplate, mode);
  }
}

TF_BUILTIN(CreateShallowArrayLiteral, ConstructorBuiltinsAssembler) {
  Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
  Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
  Node* constant_elements = Parameter(Descriptor::kConstantElements);
  Node* context = Parameter(Descriptor::kContext);
  Label call_runtime(this, Label::kDeferred);
  Return(EmitCreateShallowArrayLiteral(feedback_vector, slot, context,
                                       &call_runtime,
                                       DONT_TRACK_ALLOCATION_SITE));

  BIND(&call_runtime);
  {
    Comment("call runtime");
    int const flags =
        AggregateLiteral::kDisableMementos | AggregateLiteral::kIsShallow;
    Return(CallRuntime(Runtime::kCreateArrayLiteral, context, feedback_vector,
                       SmiTag(slot), constant_elements, SmiConstant(flags)));
  }
}

Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
    Node* feedback_vector, Node* slot, Node* context) {
  // Array literals always have a valid AllocationSite to properly track
  // elements transitions.
  TNode<Object> maybe_allocation_site =
      CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
  TVARIABLE(AllocationSite, allocation_site);

  Label create_empty_array(this),
      initialize_allocation_site(this, Label::kDeferred), done(this);
  GotoIf(TaggedIsSmi(maybe_allocation_site), &initialize_allocation_site);
  {
    allocation_site = CAST(maybe_allocation_site);
    Goto(&create_empty_array);
  }
  // TODO(cbruni): create the AllocationSite in CSA.
  BIND(&initialize_allocation_site);
  {
    allocation_site =
        CreateAllocationSiteInFeedbackVector(feedback_vector, SmiTag(slot));
    Goto(&create_empty_array);
  }

  BIND(&create_empty_array);
  TNode<Int32T> kind = LoadElementsKind(allocation_site.value());
  TNode<Context> native_context = LoadNativeContext(context);
  Comment("LoadJSArrayElementsMap");
  TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context);
  TNode<Smi> zero = SmiConstant(0);
  Comment("Allocate JSArray");
  TNode<JSArray> result =
      AllocateJSArray(GetInitialFastElementsKind(), array_map, zero, zero,
                      allocation_site.value(), ParameterMode::SMI_PARAMETERS);

  Goto(&done);
  BIND(&done);

  return result;
}

TF_BUILTIN(CreateEmptyArrayLiteral, ConstructorBuiltinsAssembler) {
  Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
  Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
  Node* context = Parameter(Descriptor::kContext);
  Node* result = EmitCreateEmptyArrayLiteral(feedback_vector, slot, context);
  Return(result);
}

Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral(
    Node* feedback_vector, Node* slot, Label* call_runtime) {
  TNode<Object> maybe_allocation_site =
      CAST(LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
  GotoIf(NotHasBoilerplate(maybe_allocation_site), call_runtime);

  TNode<AllocationSite> allocation_site = CAST(maybe_allocation_site);
  TNode<JSObject> boilerplate = LoadBoilerplate(allocation_site);
  TNode<Map> boilerplate_map = LoadMap(boilerplate);
  CSA_ASSERT(this, IsJSObjectMap(boilerplate_map));

  VARIABLE(var_properties, MachineRepresentation::kTagged);
  {
    Node* bit_field_3 = LoadMapBitField3(boilerplate_map);
    GotoIf(IsSetWord32<Map::IsDeprecatedBit>(bit_field_3), call_runtime);
    // Directly copy over the property store for dict-mode boilerplates.
    Label if_dictionary(this), if_fast(this), done(this);
    Branch(IsSetWord32<Map::IsDictionaryMapBit>(bit_field_3), &if_dictionary,
           &if_fast);
    BIND(&if_dictionary);
    {
      Comment("Copy dictionary properties");
      var_properties.Bind(CopyNameDictionary(
          CAST(LoadSlowProperties(boilerplate)), call_runtime));
      // Slow objects have no in-object properties.
      Goto(&done);
    }
    BIND(&if_fast);
    {
      // TODO(cbruni): support copying out-of-object properties.
      Node* boilerplate_properties = LoadFastProperties(boilerplate);
      GotoIfNot(IsEmptyFixedArray(boilerplate_properties), call_runtime);
      var_properties.Bind(EmptyFixedArrayConstant());
      Goto(&done);
    }
    BIND(&done);
  }

  VARIABLE(var_elements, MachineRepresentation::kTagged);
  {
    // Copy the elements backing store, assuming that it's flat.
    Label if_empty_fixed_array(this), if_copy_elements(this), done(this);
    Node* boilerplate_elements = LoadElements(boilerplate);
    Branch(IsEmptyFixedArray(boilerplate_elements), &if_empty_fixed_array,
           &if_copy_elements);

    BIND(&if_empty_fixed_array);
    var_elements.Bind(boilerplate_elements);
    Goto(&done);

    BIND(&if_copy_elements);
    CSA_ASSERT(this, Word32BinaryNot(
                         IsFixedCOWArrayMap(LoadMap(boilerplate_elements))));
    ExtractFixedArrayFlags flags;
    flags |= ExtractFixedArrayFlag::kAllFixedArrays;
    flags |= ExtractFixedArrayFlag::kNewSpaceAllocationOnly;
    flags |= ExtractFixedArrayFlag::kDontCopyCOW;
    var_elements.Bind(CloneFixedArray(boilerplate_elements, flags));
    Goto(&done);
    BIND(&done);
  }

  // Ensure new-space allocation for a fresh JSObject so we can skip write
  // barriers when copying all object fields.
  STATIC_ASSERT(JSObject::kMaxInstanceSize < kMaxRegularHeapObjectSize);
  TNode<IntPtrT> instance_size =
      TimesTaggedSize(LoadMapInstanceSizeInWords(boilerplate_map));
  TNode<IntPtrT> allocation_size = instance_size;
  bool needs_allocation_memento = FLAG_allocation_site_pretenuring;
  if (needs_allocation_memento) {
    // Prepare for inner-allocating the AllocationMemento.
    allocation_size =
        IntPtrAdd(instance_size, IntPtrConstant(AllocationMemento::kSize));
  }

  TNode<HeapObject> copy =
      UncheckedCast<HeapObject>(AllocateInNewSpace(allocation_size));
  {
    Comment("Initialize Literal Copy");
    // Initialize Object fields.
    StoreMapNoWriteBarrier(copy, boilerplate_map);
    StoreObjectFieldNoWriteBarrier(copy, JSObject::kPropertiesOrHashOffset,
                                   var_properties.value());
    StoreObjectFieldNoWriteBarrier(copy, JSObject::kElementsOffset,
                                   var_elements.value());
  }

  // Initialize the AllocationMemento before potential GCs due to heap number
  // allocation when copying the in-object properties.
  if (needs_allocation_memento) {
    InitializeAllocationMemento(copy, instance_size, allocation_site);
  }

  {
    // Copy over in-object properties.
    Label continue_with_write_barrier(this), done_init(this);
    TVARIABLE(IntPtrT, offset, IntPtrConstant(JSObject::kHeaderSize));
    // Mutable heap numbers only occur on 32-bit platforms.
    bool may_use_mutable_heap_numbers = !FLAG_unbox_double_fields;
    {
      Comment("Copy in-object properties fast");
      Label continue_fast(this, &offset);
      Branch(WordEqual(offset.value(), instance_size), &done_init,
             &continue_fast);
      BIND(&continue_fast);
      if (may_use_mutable_heap_numbers) {
        TNode<Object> field = LoadObjectField(boilerplate, offset.value());
        Label store_field(this);
        GotoIf(TaggedIsSmi(field), &store_field);
        GotoIf(IsMutableHeapNumber(CAST(field)), &continue_with_write_barrier);
        Goto(&store_field);
        BIND(&store_field);
        StoreObjectFieldNoWriteBarrier(copy, offset.value(), field);
      } else {
        // Copy fields as raw data.
        TNode<IntPtrT> field =
            LoadObjectField<IntPtrT>(boilerplate, offset.value());
        StoreObjectFieldNoWriteBarrier(copy, offset.value(), field);
      }
      offset = IntPtrAdd(offset.value(), IntPtrConstant(kTaggedSize));
      Branch(WordNotEqual(offset.value(), instance_size), &continue_fast,
             &done_init);
    }

    if (!may_use_mutable_heap_numbers) {
      BIND(&done_init);
      return copy;
    }
    // Continue initializing the literal after seeing the first sub-object
    // potentially causing allocation. In this case we prepare the new literal
    // by copying all pending fields over from the boilerplate and emit full
    // write barriers from here on.
    BIND(&continue_with_write_barrier);
    {
      Comment("Copy in-object properties slow");
      BuildFastLoop(
          offset.value(), instance_size,
          [=](Node* offset) {
            // TODO(ishell): value decompression is not necessary here.
            Node* field = LoadObjectField(boilerplate, offset);
            StoreObjectFieldNoWriteBarrier(copy, offset, field);
          },
          kTaggedSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
      Comment("Copy mutable HeapNumber values");
      BuildFastLoop(
          offset.value(), instance_size,
          [=](Node* offset) {
            Node* field = LoadObjectField(copy, offset);
            Label copy_mutable_heap_number(this, Label::kDeferred),
                continue_loop(this);
            // We only have to clone complex field values.
            GotoIf(TaggedIsSmi(field), &continue_loop);
            Branch(IsMutableHeapNumber(field), &copy_mutable_heap_number,
                   &continue_loop);
            BIND(&copy_mutable_heap_number);
            {
              Node* double_value = LoadHeapNumberValue(field);
              Node* mutable_heap_number =
                  AllocateMutableHeapNumberWithValue(double_value);
              StoreObjectField(copy, offset, mutable_heap_number);
              Goto(&continue_loop);
            }
            BIND(&continue_loop);
          },
          kTaggedSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
      Goto(&done_init);
    }
    BIND(&done_init);
  }
  return copy;
}

TF_BUILTIN(CreateShallowObjectLiteral, ConstructorBuiltinsAssembler) {
  Label call_runtime(this);
  Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
  Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
  Node* copy =
      EmitCreateShallowObjectLiteral(feedback_vector, slot, &call_runtime);
  Return(copy);

  BIND(&call_runtime);
  Node* object_boilerplate_description =
      Parameter(Descriptor::kObjectBoilerplateDescription);
  Node* flags = Parameter(Descriptor::kFlags);
  Node* context = Parameter(Descriptor::kContext);
  TailCallRuntime(Runtime::kCreateObjectLiteral, context, feedback_vector,
                  SmiTag(slot), object_boilerplate_description, flags);
}

// Used by the CreateEmptyObjectLiteral bytecode and the Object constructor.
Node* ConstructorBuiltinsAssembler::EmitCreateEmptyObjectLiteral(
    Node* context) {
  Node* native_context = LoadNativeContext(context);
  Node* object_function =
      LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX);
  Node* map = LoadObjectField(object_function,
                              JSFunction::kPrototypeOrInitialMapOffset);
  CSA_ASSERT(this, IsMap(map));
  // Ensure that slack tracking is disabled for the map.
  STATIC_ASSERT(Map::kNoSlackTracking == 0);
  CSA_ASSERT(
      this, IsClearWord32<Map::ConstructionCounterBits>(LoadMapBitField3(map)));
  Node* empty_fixed_array = EmptyFixedArrayConstant();
  Node* result =
      AllocateJSObjectFromMap(map, empty_fixed_array, empty_fixed_array);
  return result;
}

// ES #sec-object-constructor
TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) {
  int const kValueArg = 0;
  Node* argc =
      ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
  CodeStubArguments args(this, argc);
  Node* context = Parameter(Descriptor::kContext);
  Node* new_target = Parameter(Descriptor::kJSNewTarget);

  VARIABLE(var_result, MachineRepresentation::kTagged);
  Label if_subclass(this, Label::kDeferred), if_notsubclass(this),
      return_result(this);
  GotoIf(IsUndefined(new_target), &if_notsubclass);
  TNode<JSFunction> target = CAST(Parameter(Descriptor::kJSTarget));
  Branch(WordEqual(new_target, target), &if_notsubclass, &if_subclass);

  BIND(&if_subclass);
  {
    Node* result =
        CallBuiltin(Builtins::kFastNewObject, context, target, new_target);
    var_result.Bind(result);
    Goto(&return_result);
  }

  BIND(&if_notsubclass);
  {
    Label if_newobject(this, Label::kDeferred), if_toobject(this);

    Node* value_index = IntPtrConstant(kValueArg);
    GotoIf(UintPtrGreaterThanOrEqual(value_index, argc), &if_newobject);
    Node* value = args.AtIndex(value_index);
    GotoIf(IsNull(value), &if_newobject);
    Branch(IsUndefined(value), &if_newobject, &if_toobject);

    BIND(&if_newobject);
    {
      Node* result = EmitCreateEmptyObjectLiteral(context);
      var_result.Bind(result);
      Goto(&return_result);
    }

    BIND(&if_toobject);
    {
      Node* result = CallBuiltin(Builtins::kToObject, context, value);
      var_result.Bind(result);
      Goto(&return_result);
    }
  }

  BIND(&return_result);
  args.PopAndReturn(var_result.value());
}

// ES #sec-number-constructor
TF_BUILTIN(NumberConstructor, ConstructorBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* argc =
      ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
  CodeStubArguments args(this, argc);

  // 1. If no arguments were passed to this function invocation, let n be +0.
  VARIABLE(var_n, MachineRepresentation::kTagged, SmiConstant(0));
  Label if_nloaded(this, &var_n);
  GotoIf(WordEqual(argc, IntPtrConstant(0)), &if_nloaded);

  // 2. Else,
  //    a. Let prim be ? ToNumeric(value).
  //    b. If Type(prim) is BigInt, let n be the Number value for prim.
  //    c. Otherwise, let n be prim.
  Node* value = args.AtIndex(0);
  var_n.Bind(ToNumber(context, value, BigIntHandling::kConvertToNumber));
  Goto(&if_nloaded);

  BIND(&if_nloaded);
  {
    // 3. If NewTarget is undefined, return n.
    Node* n_value = var_n.value();
    Node* new_target = Parameter(Descriptor::kJSNewTarget);
    Label return_n(this), constructnumber(this, Label::kDeferred);
    Branch(IsUndefined(new_target), &return_n, &constructnumber);

    BIND(&return_n);
    { args.PopAndReturn(n_value); }

    BIND(&constructnumber);
    {
      // 4. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
      //    "%NumberPrototype%", « [[NumberData]] »).
      // 5. Set O.[[NumberData]] to n.
      // 6. Return O.

      // We are not using Parameter(Descriptor::kJSTarget) and loading the value
      // from the current frame here in order to reduce register pressure on the
      // fast path.
      TNode<JSFunction> target = LoadTargetFromFrame();
      Node* result =
          CallBuiltin(Builtins::kFastNewObject, context, target, new_target);
      StoreObjectField(result, JSPrimitiveWrapper::kValueOffset, n_value);
      args.PopAndReturn(result);
    }
  }
}

TF_BUILTIN(GenericLazyDeoptContinuation, ConstructorBuiltinsAssembler) {
  Node* result = Parameter(Descriptor::kResult);
  Return(result);
}

// https://tc39.github.io/ecma262/#sec-string-constructor
TF_BUILTIN(StringConstructor, ConstructorBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* argc =
      ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
  CodeStubArguments args(this, argc);

  TNode<Object> new_target = CAST(Parameter(Descriptor::kJSNewTarget));

  // 1. If no arguments were passed to this function invocation, let s be "".
  VARIABLE(var_s, MachineRepresentation::kTagged, EmptyStringConstant());
  Label if_sloaded(this, &var_s);
  GotoIf(WordEqual(argc, IntPtrConstant(0)), &if_sloaded);

  // 2. Else,
  //    a. If NewTarget is undefined [...]
  Node* value = args.AtIndex(0);
  Label if_tostring(this, &var_s);
  GotoIfNot(IsUndefined(new_target), &if_tostring);

  // 2a. [...] and Type(value) is Symbol, return SymbolDescriptiveString(value).
  GotoIf(TaggedIsSmi(value), &if_tostring);
  GotoIfNot(IsSymbol(value), &if_tostring);
  {
    Node* result =
        CallRuntime(Runtime::kSymbolDescriptiveString, context, value);
    args.PopAndReturn(result);
  }

  // 2b. Let s be ? ToString(value).
  BIND(&if_tostring);
  {
    var_s.Bind(CallBuiltin(Builtins::kToString, context, value));
    Goto(&if_sloaded);
  }

  // 3. If NewTarget is undefined, return s.
  BIND(&if_sloaded);
  {
    Node* s_value = var_s.value();
    Label return_s(this), constructstring(this, Label::kDeferred);
    Branch(IsUndefined(new_target), &return_s, &constructstring);

    BIND(&return_s);
    { args.PopAndReturn(s_value); }

    BIND(&constructstring);
    {
      // We are not using Parameter(Descriptor::kJSTarget) and loading the value
      // from the current frame here in order to reduce register pressure on the
      // fast path.
      TNode<JSFunction> target = LoadTargetFromFrame();

      Node* result =
          CallBuiltin(Builtins::kFastNewObject, context, target, new_target);
      StoreObjectField(result, JSPrimitiveWrapper::kValueOffset, s_value);
      args.PopAndReturn(result);
    }
  }
}

}  // namespace internal
}  // namespace v8
