// 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-utils.h"
#include "src/builtins/builtins.h"
#include "src/code-stub-assembler.h"
#include "src/counters.h"
#include "src/interface-descriptors.h"
#include "src/macro-assembler.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {

BUILTIN(Illegal) {
  UNREACHABLE();
  return isolate->heap()->undefined_value();  // Make compiler happy.
}

BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }

BUILTIN(UnsupportedThrower) {
  HandleScope scope(isolate);
  THROW_NEW_ERROR_RETURN_FAILURE(isolate,
                                 NewError(MessageTemplate::kUnsupported));
}

// -----------------------------------------------------------------------------
// Throwers for restricted function properties and strict arguments object
// properties

BUILTIN(RestrictedFunctionPropertiesThrower) {
  HandleScope scope(isolate);
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
}

BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
  HandleScope scope(isolate);
  THROW_NEW_ERROR_RETURN_FAILURE(
      isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
}

// -----------------------------------------------------------------------------
// Interrupt and stack checks.

void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
  masm->TailCallRuntime(Runtime::kInterrupt);
}

void Builtins::Generate_StackCheck(MacroAssembler* masm) {
  masm->TailCallRuntime(Runtime::kStackGuard);
}

// -----------------------------------------------------------------------------
// TurboFan support builtins.

void Builtins::Generate_CopyFastSmiOrObjectElements(
    compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef compiler::Node Node;
  typedef CopyFastSmiOrObjectElementsDescriptor Descriptor;
  CodeStubAssembler assembler(state);

  Node* object = assembler.Parameter(Descriptor::kObject);

  // Load the {object}s elements.
  Node* source = assembler.LoadObjectField(object, JSObject::kElementsOffset);

  CodeStubAssembler::ParameterMode mode = assembler.OptimalParameterMode();
  Node* length = assembler.TaggedToParameter(
      assembler.LoadFixedArrayBaseLength(source), mode);

  // Check if we can allocate in new space.
  ElementsKind kind = FAST_ELEMENTS;
  int max_elements = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
  Label if_newspace(&assembler), if_oldspace(&assembler);
  assembler.Branch(
      assembler.UintPtrOrSmiLessThan(
          length, assembler.IntPtrOrSmiConstant(max_elements, mode), mode),
      &if_newspace, &if_oldspace);

  assembler.Bind(&if_newspace);
  {
    Node* target = assembler.AllocateFixedArray(kind, length, mode);
    assembler.CopyFixedArrayElements(kind, source, target, length,
                                     SKIP_WRITE_BARRIER, mode);
    assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
    assembler.Return(target);
  }

  assembler.Bind(&if_oldspace);
  {
    Node* target = assembler.AllocateFixedArray(kind, length, mode,
                                                CodeStubAssembler::kPretenured);
    assembler.CopyFixedArrayElements(kind, source, target, length,
                                     UPDATE_WRITE_BARRIER, mode);
    assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
    assembler.Return(target);
  }
}

void Builtins::Generate_GrowFastDoubleElements(
    compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef compiler::Node Node;
  typedef GrowArrayElementsDescriptor Descriptor;
  CodeStubAssembler assembler(state);

  Node* object = assembler.Parameter(Descriptor::kObject);
  Node* key = assembler.Parameter(Descriptor::kKey);
  Node* context = assembler.Parameter(Descriptor::kContext);

  Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
  Node* elements = assembler.LoadElements(object);
  elements = assembler.TryGrowElementsCapacity(
      object, elements, FAST_DOUBLE_ELEMENTS, key, &runtime);
  assembler.Return(elements);

  assembler.Bind(&runtime);
  assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
}

void Builtins::Generate_GrowFastSmiOrObjectElements(
    compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef compiler::Node Node;
  typedef GrowArrayElementsDescriptor Descriptor;
  CodeStubAssembler assembler(state);

  Node* object = assembler.Parameter(Descriptor::kObject);
  Node* key = assembler.Parameter(Descriptor::kKey);
  Node* context = assembler.Parameter(Descriptor::kContext);

  Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
  Node* elements = assembler.LoadElements(object);
  elements = assembler.TryGrowElementsCapacity(object, elements, FAST_ELEMENTS,
                                               key, &runtime);
  assembler.Return(elements);

  assembler.Bind(&runtime);
  assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
}

namespace {

void Generate_NewArgumentsElements(CodeStubAssembler* assembler,
                                   compiler::Node* frame,
                                   compiler::Node* length) {
  typedef CodeStubAssembler::Label Label;
  typedef CodeStubAssembler::Variable Variable;
  typedef compiler::Node Node;

  // Check if we can allocate in new space.
  ElementsKind kind = FAST_ELEMENTS;
  int max_elements = FixedArray::GetMaxLengthForNewSpaceAllocation(kind);
  Label if_newspace(assembler), if_oldspace(assembler, Label::kDeferred);
  assembler->Branch(assembler->IntPtrLessThan(
                        length, assembler->IntPtrConstant(max_elements)),
                    &if_newspace, &if_oldspace);

  assembler->Bind(&if_newspace);
  {
    // Prefer EmptyFixedArray in case of non-positive {length} (the {length}
    // can be negative here for rest parameters).
    Label if_empty(assembler), if_notempty(assembler);
    assembler->Branch(
        assembler->IntPtrLessThanOrEqual(length, assembler->IntPtrConstant(0)),
        &if_empty, &if_notempty);

    assembler->Bind(&if_empty);
    assembler->Return(assembler->EmptyFixedArrayConstant());

    assembler->Bind(&if_notempty);
    {
      // Allocate a FixedArray in new space.
      Node* result = assembler->AllocateFixedArray(kind, length);

      // Compute the effective {offset} into the {frame}.
      Node* offset = assembler->IntPtrAdd(length, assembler->IntPtrConstant(1));

      // Copy the parameters from {frame} (starting at {offset}) to {result}.
      Variable var_index(assembler, MachineType::PointerRepresentation());
      Label loop(assembler, &var_index), done_loop(assembler);
      var_index.Bind(assembler->IntPtrConstant(0));
      assembler->Goto(&loop);
      assembler->Bind(&loop);
      {
        // Load the current {index}.
        Node* index = var_index.value();

        // Check if we are done.
        assembler->GotoIf(assembler->WordEqual(index, length), &done_loop);

        // Load the parameter at the given {index}.
        Node* value = assembler->Load(
            MachineType::AnyTagged(), frame,
            assembler->WordShl(assembler->IntPtrSub(offset, index),
                               assembler->IntPtrConstant(kPointerSizeLog2)));

        // Store the {value} into the {result}.
        assembler->StoreFixedArrayElement(result, index, value,
                                          SKIP_WRITE_BARRIER);

        // Continue with next {index}.
        var_index.Bind(
            assembler->IntPtrAdd(index, assembler->IntPtrConstant(1)));
        assembler->Goto(&loop);
      }

      assembler->Bind(&done_loop);
      assembler->Return(result);
    }
  }

  assembler->Bind(&if_oldspace);
  {
    // Allocate in old space (or large object space).
    assembler->TailCallRuntime(
        Runtime::kNewArgumentsElements, assembler->NoContextConstant(),
        assembler->BitcastWordToTagged(frame), assembler->SmiFromWord(length));
  }
}

}  // namespace

void Builtins::Generate_NewUnmappedArgumentsElements(
    compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef CodeStubAssembler::Variable Variable;
  typedef compiler::Node Node;
  typedef NewArgumentsElementsDescriptor Descriptor;
  CodeStubAssembler assembler(state);

  Node* formal_parameter_count =
      assembler.Parameter(Descriptor::kFormalParameterCount);

  // Determine the frame that holds the parameters.
  Label done(&assembler);
  Variable var_frame(&assembler, MachineType::PointerRepresentation()),
      var_length(&assembler, MachineType::PointerRepresentation());
  var_frame.Bind(assembler.LoadParentFramePointer());
  var_length.Bind(formal_parameter_count);
  Node* parent_frame = assembler.Load(
      MachineType::Pointer(), var_frame.value(),
      assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
  Node* parent_frame_type =
      assembler.Load(MachineType::AnyTagged(), parent_frame,
                     assembler.IntPtrConstant(
                         CommonFrameConstants::kContextOrFrameTypeOffset));
  assembler.GotoIfNot(assembler.MarkerIsFrameType(
                          parent_frame_type, StackFrame::ARGUMENTS_ADAPTOR),
                      &done);
  {
    // Determine the length from the ArgumentsAdaptorFrame.
    Node* length = assembler.LoadAndUntagSmi(
        parent_frame, ArgumentsAdaptorFrameConstants::kLengthOffset);

    // Take the arguments from the ArgumentsAdaptorFrame.
    var_frame.Bind(parent_frame);
    var_length.Bind(length);
  }
  assembler.Goto(&done);

  // Allocate the actual FixedArray for the elements.
  assembler.Bind(&done);
  Generate_NewArgumentsElements(&assembler, var_frame.value(),
                                var_length.value());
}

void Builtins::Generate_NewRestParameterElements(
    compiler::CodeAssemblerState* state) {
  typedef CodeStubAssembler::Label Label;
  typedef compiler::Node Node;
  typedef NewArgumentsElementsDescriptor Descriptor;
  CodeStubAssembler assembler(state);

  Node* formal_parameter_count =
      assembler.Parameter(Descriptor::kFormalParameterCount);

  // Check if we have an ArgumentsAdaptorFrame, as we will only have rest
  // parameters in that case.
  Label if_empty(&assembler);
  Node* frame = assembler.Load(
      MachineType::Pointer(), assembler.LoadParentFramePointer(),
      assembler.IntPtrConstant(StandardFrameConstants::kCallerFPOffset));
  Node* frame_type =
      assembler.Load(MachineType::AnyTagged(), frame,
                     assembler.IntPtrConstant(
                         CommonFrameConstants::kContextOrFrameTypeOffset));
  assembler.GotoIfNot(
      assembler.MarkerIsFrameType(frame_type, StackFrame::ARGUMENTS_ADAPTOR),
      &if_empty);

  // Determine the length from the ArgumentsAdaptorFrame.
  Node* frame_length = assembler.LoadAndUntagSmi(
      frame, ArgumentsAdaptorFrameConstants::kLengthOffset);

  // Compute the actual rest parameter length (may be negative).
  Node* length = assembler.IntPtrSub(frame_length, formal_parameter_count);

  // Allocate the actual FixedArray for the elements.
  Generate_NewArgumentsElements(&assembler, frame, length);

  // No rest parameters, return an empty FixedArray.
  assembler.Bind(&if_empty);
  assembler.Return(assembler.EmptyFixedArrayConstant());
}

void Builtins::Generate_ReturnReceiver(compiler::CodeAssemblerState* state) {
  CodeStubAssembler assembler(state);
  assembler.Return(assembler.Parameter(0));
}

}  // namespace internal
}  // namespace v8
