chromium/v8/src/builtins/builtins-internal-gen.cc

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

#include "src/api/api.h"
#include "src/baseline/baseline.h"
#include "src/builtins/builtins-inl.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/codegen/code-stub-assembler-inl.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/macro-assembler-inl.h"
#include "src/common/globals.h"
#include "src/execution/frame-constants.h"
#include "src/heap/mutable-page-metadata.h"
#include "src/ic/accessor-assembler.h"
#include "src/ic/keyed-store-generic.h"
#include "src/logging/counters.h"
#include "src/objects/debug-objects.h"
#include "src/objects/scope-info.h"
#include "src/objects/shared-function-info.h"
#include "src/runtime/runtime.h"

namespace v8 {
namespace internal {

#include "src/codegen/define-code-stub-assembler-macros.inc"

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

TF_BUILTIN(CopyFastSmiOrObjectElements, CodeStubAssembler) {}

TF_BUILTIN(GrowFastDoubleElements, CodeStubAssembler) {}

TF_BUILTIN(GrowFastSmiOrObjectElements, CodeStubAssembler) {}

TF_BUILTIN(ReturnReceiver, CodeStubAssembler) {}

TF_BUILTIN(DebugBreakTrampoline, CodeStubAssembler) {}

class WriteBarrierCodeStubAssembler : public CodeStubAssembler {};

TF_BUILTIN(RecordWriteSaveFP, WriteBarrierCodeStubAssembler) {}

TF_BUILTIN(RecordWriteIgnoreFP, WriteBarrierCodeStubAssembler) {}

TF_BUILTIN(IndirectPointerBarrierSaveFP, WriteBarrierCodeStubAssembler) {}

TF_BUILTIN(IndirectPointerBarrierIgnoreFP, WriteBarrierCodeStubAssembler) {}

TF_BUILTIN(EphemeronKeyBarrierSaveFP, WriteBarrierCodeStubAssembler) {}

TF_BUILTIN(EphemeronKeyBarrierIgnoreFP, WriteBarrierCodeStubAssembler) {}

#ifdef V8_IS_TSAN
class TSANRelaxedStoreCodeStubAssembler : public CodeStubAssembler {
 public:
  explicit TSANRelaxedStoreCodeStubAssembler(
      compiler::CodeAssemblerState* state)
      : CodeStubAssembler(state) {}

  TNode<ExternalReference> GetExternalReference(int size) {
    if (size == kInt8Size) {
      return ExternalConstant(
          ExternalReference::tsan_relaxed_store_function_8_bits());
    } else if (size == kInt16Size) {
      return ExternalConstant(
          ExternalReference::tsan_relaxed_store_function_16_bits());
    } else if (size == kInt32Size) {
      return ExternalConstant(
          ExternalReference::tsan_relaxed_store_function_32_bits());
    } else {
      CHECK_EQ(size, kInt64Size);
      return ExternalConstant(
          ExternalReference::tsan_relaxed_store_function_64_bits());
    }
  }

  void GenerateTSANRelaxedStore(SaveFPRegsMode fp_mode, int size) {
    TNode<ExternalReference> function = GetExternalReference(size);
    auto address = UncheckedParameter<IntPtrT>(TSANStoreDescriptor::kAddress);
    TNode<IntPtrT> value = BitcastTaggedToWord(
        UncheckedParameter<Object>(TSANStoreDescriptor::kValue));
    CallCFunctionWithCallerSavedRegisters(
        function, MachineType::Int32(), fp_mode,
        std::make_pair(MachineType::IntPtr(), address),
        std::make_pair(MachineType::IntPtr(), value));
    Return(UndefinedConstant());
  }
};

TF_BUILTIN(TSANRelaxedStore8IgnoreFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kIgnore, kInt8Size);
}

TF_BUILTIN(TSANRelaxedStore8SaveFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kSave, kInt8Size);
}

TF_BUILTIN(TSANRelaxedStore16IgnoreFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kIgnore, kInt16Size);
}

TF_BUILTIN(TSANRelaxedStore16SaveFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kSave, kInt16Size);
}

TF_BUILTIN(TSANRelaxedStore32IgnoreFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kIgnore, kInt32Size);
}

TF_BUILTIN(TSANRelaxedStore32SaveFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kSave, kInt32Size);
}

TF_BUILTIN(TSANRelaxedStore64IgnoreFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kIgnore, kInt64Size);
}

TF_BUILTIN(TSANRelaxedStore64SaveFP, TSANRelaxedStoreCodeStubAssembler) {
  GenerateTSANRelaxedStore(SaveFPRegsMode::kSave, kInt64Size);
}

class TSANSeqCstStoreCodeStubAssembler : public CodeStubAssembler {
 public:
  explicit TSANSeqCstStoreCodeStubAssembler(compiler::CodeAssemblerState* state)
      : CodeStubAssembler(state) {}

  TNode<ExternalReference> GetExternalReference(int size) {
    if (size == kInt8Size) {
      return ExternalConstant(
          ExternalReference::tsan_seq_cst_store_function_8_bits());
    } else if (size == kInt16Size) {
      return ExternalConstant(
          ExternalReference::tsan_seq_cst_store_function_16_bits());
    } else if (size == kInt32Size) {
      return ExternalConstant(
          ExternalReference::tsan_seq_cst_store_function_32_bits());
    } else {
      CHECK_EQ(size, kInt64Size);
      return ExternalConstant(
          ExternalReference::tsan_seq_cst_store_function_64_bits());
    }
  }

  void GenerateTSANSeqCstStore(SaveFPRegsMode fp_mode, int size) {
    TNode<ExternalReference> function = GetExternalReference(size);
    auto address = UncheckedParameter<IntPtrT>(TSANStoreDescriptor::kAddress);
    TNode<IntPtrT> value = BitcastTaggedToWord(
        UncheckedParameter<Object>(TSANStoreDescriptor::kValue));
    CallCFunctionWithCallerSavedRegisters(
        function, MachineType::Int32(), fp_mode,
        std::make_pair(MachineType::IntPtr(), address),
        std::make_pair(MachineType::IntPtr(), value));
    Return(UndefinedConstant());
  }
};

TF_BUILTIN(TSANSeqCstStore8IgnoreFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kIgnore, kInt8Size);
}

TF_BUILTIN(TSANSeqCstStore8SaveFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kSave, kInt8Size);
}

TF_BUILTIN(TSANSeqCstStore16IgnoreFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kIgnore, kInt16Size);
}

TF_BUILTIN(TSANSeqCstStore16SaveFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kSave, kInt16Size);
}

TF_BUILTIN(TSANSeqCstStore32IgnoreFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kIgnore, kInt32Size);
}

TF_BUILTIN(TSANSeqCstStore32SaveFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kSave, kInt32Size);
}

TF_BUILTIN(TSANSeqCstStore64IgnoreFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kIgnore, kInt64Size);
}

TF_BUILTIN(TSANSeqCstStore64SaveFP, TSANSeqCstStoreCodeStubAssembler) {
  GenerateTSANSeqCstStore(SaveFPRegsMode::kSave, kInt64Size);
}

class TSANRelaxedLoadCodeStubAssembler : public CodeStubAssembler {
 public:
  explicit TSANRelaxedLoadCodeStubAssembler(compiler::CodeAssemblerState* state)
      : CodeStubAssembler(state) {}

  TNode<ExternalReference> GetExternalReference(int size) {
    if (size == kInt32Size) {
      return ExternalConstant(
          ExternalReference::tsan_relaxed_load_function_32_bits());
    } else {
      CHECK_EQ(size, kInt64Size);
      return ExternalConstant(
          ExternalReference::tsan_relaxed_load_function_64_bits());
    }
  }

  void GenerateTSANRelaxedLoad(SaveFPRegsMode fp_mode, int size) {
    TNode<ExternalReference> function = GetExternalReference(size);
    auto address = UncheckedParameter<IntPtrT>(TSANLoadDescriptor::kAddress);
    CallCFunctionWithCallerSavedRegisters(
        function, MachineType::Int32(), fp_mode,
        std::make_pair(MachineType::IntPtr(), address));
    Return(UndefinedConstant());
  }
};

TF_BUILTIN(TSANRelaxedLoad32IgnoreFP, TSANRelaxedLoadCodeStubAssembler) {
  GenerateTSANRelaxedLoad(SaveFPRegsMode::kIgnore, kInt32Size);
}

TF_BUILTIN(TSANRelaxedLoad32SaveFP, TSANRelaxedLoadCodeStubAssembler) {
  GenerateTSANRelaxedLoad(SaveFPRegsMode::kSave, kInt32Size);
}

TF_BUILTIN(TSANRelaxedLoad64IgnoreFP, TSANRelaxedLoadCodeStubAssembler) {
  GenerateTSANRelaxedLoad(SaveFPRegsMode::kIgnore, kInt64Size);
}

TF_BUILTIN(TSANRelaxedLoad64SaveFP, TSANRelaxedLoadCodeStubAssembler) {
  GenerateTSANRelaxedLoad(SaveFPRegsMode::kSave, kInt64Size);
}
#endif  // V8_IS_TSAN

class DeletePropertyBaseAssembler : public AccessorAssembler {};

TF_BUILTIN(DeleteProperty, DeletePropertyBaseAssembler) {}

namespace {

class SetOrCopyDataPropertiesAssembler : public CodeStubAssembler {};

}  // namespace

TF_BUILTIN(CopyDataPropertiesWithExcludedPropertiesOnStack,
           SetOrCopyDataPropertiesAssembler) {}

TF_BUILTIN(CopyDataPropertiesWithExcludedProperties,
           SetOrCopyDataPropertiesAssembler) {}

// ES #sec-copydataproperties
TF_BUILTIN(CopyDataProperties, SetOrCopyDataPropertiesAssembler) {}

TF_BUILTIN(SetDataProperties, SetOrCopyDataPropertiesAssembler) {}

TF_BUILTIN(ForInEnumerate, CodeStubAssembler) {}

TF_BUILTIN(ForInPrepare, CodeStubAssembler) {}

TF_BUILTIN(ForInFilter, CodeStubAssembler) {}

TF_BUILTIN(SameValue, CodeStubAssembler) {}

TF_BUILTIN(SameValueNumbersOnly, CodeStubAssembler) {}

TF_BUILTIN(AdaptorWithBuiltinExitFrame, CodeStubAssembler) {}

TF_BUILTIN(NewHeapNumber, CodeStubAssembler) {}

TF_BUILTIN(AllocateInYoungGeneration, CodeStubAssembler) {}

TF_BUILTIN(AllocateInOldGeneration, CodeStubAssembler) {}

#if V8_ENABLE_WEBASSEMBLY
TF_BUILTIN(WasmAllocateInYoungGeneration, CodeStubAssembler) {}

TF_BUILTIN(WasmAllocateInOldGeneration, CodeStubAssembler) {}
#endif

TF_BUILTIN(Abort, CodeStubAssembler) {}

TF_BUILTIN(AbortCSADcheck, CodeStubAssembler) {}

void Builtins::Generate_CEntry_Return1_ArgvOnStack_NoBuiltinExit(
    MacroAssembler* masm) {}

void Builtins::Generate_CEntry_Return1_ArgvOnStack_BuiltinExit(
    MacroAssembler* masm) {}

void Builtins::Generate_CEntry_Return1_ArgvInRegister_NoBuiltinExit(
    MacroAssembler* masm) {}

void Builtins::Generate_CEntry_Return2_ArgvOnStack_NoBuiltinExit(
    MacroAssembler* masm) {}

void Builtins::Generate_CEntry_Return2_ArgvOnStack_BuiltinExit(
    MacroAssembler* masm) {}

void Builtins::Generate_CEntry_Return2_ArgvInRegister_NoBuiltinExit(
    MacroAssembler* masm) {}

void Builtins::Generate_WasmCEntry(MacroAssembler* masm) {}

#if !defined(V8_TARGET_ARCH_ARM)
void Builtins::Generate_MemCopyUint8Uint8(MacroAssembler* masm) {}
#endif  // !defined(V8_TARGET_ARCH_ARM)

#ifndef V8_TARGET_ARCH_IA32
void Builtins::Generate_MemMove(MacroAssembler* masm) {}
#endif  // V8_TARGET_ARCH_IA32

void Builtins::Generate_BaselineLeaveFrame(MacroAssembler* masm) {}

// TODO(v8:11421): Remove #if once the Maglev compiler is ported to other
// architectures.
#ifndef V8_TARGET_ARCH_X64
void Builtins::Generate_MaglevOnStackReplacement(MacroAssembler* masm) {
  using D =
      i::CallInterfaceDescriptorFor<Builtin::kMaglevOnStackReplacement>::type;
  static_assert(D::kParameterCount == 1);
  masm->Trap();
}
#endif  // V8_TARGET_ARCH_X64

#ifdef V8_ENABLE_MAGLEV
void Builtins::Generate_MaglevOptimizeCodeOrTailCallOptimizedCodeSlot(
    MacroAssembler* masm) {}
#else
// static
void Builtins::Generate_MaglevFunctionEntryStackCheck(MacroAssembler* masm,
                                                      bool save_new_target) {
  masm->Trap();
}
void Builtins::Generate_MaglevOptimizeCodeOrTailCallOptimizedCodeSlot(
    MacroAssembler* masm) {
  masm->Trap();
}
#endif  // V8_ENABLE_MAGLEV

void Builtins::Generate_MaglevFunctionEntryStackCheck_WithoutNewTarget(
    MacroAssembler* masm) {}

void Builtins::Generate_MaglevFunctionEntryStackCheck_WithNewTarget(
    MacroAssembler* masm) {}

// ES6 [[Get]] operation.
TF_BUILTIN(GetProperty, CodeStubAssembler) {}

// ES6 [[Get]] operation with Receiver.
TF_BUILTIN(GetPropertyWithReceiver, CodeStubAssembler) {}

// ES6 [[Set]] operation.
TF_BUILTIN(SetProperty, CodeStubAssembler) {}

// ES6 CreateDataProperty(), specialized for the case where objects are still
// being initialized, and have not yet been made accessible to the user. Thus,
// any operation here should be unobservable until after the object has been
// returned.
TF_BUILTIN(CreateDataProperty, CodeStubAssembler) {}

TF_BUILTIN(InstantiateAsmJs, CodeStubAssembler) {}

TF_BUILTIN(FindNonDefaultConstructorOrConstruct, CodeStubAssembler) {}

// Dispatcher for different implementations of the [[GetOwnProperty]] internal
// method, returning a PropertyDescriptorObject (a Struct representation of the
// spec PropertyDescriptor concept)
TF_BUILTIN(GetOwnPropertyDescriptor, CodeStubAssembler) {}

#include "src/codegen/undef-code-stub-assembler-macros.inc"

}  // namespace internal
}  // namespace v8