11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h"
81cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_civoid CallInterfaceDescriptorData::InitializeRegisters(
141cb0ef41Sopenharmony_ci    Flags flags, int return_count, int parameter_count,
151cb0ef41Sopenharmony_ci    StackArgumentOrder stack_order, int register_parameter_count,
161cb0ef41Sopenharmony_ci    const Register* registers) {
171cb0ef41Sopenharmony_ci  DCHECK(!IsInitializedTypes());
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci#ifdef DEBUG
201cb0ef41Sopenharmony_ci  {
211cb0ef41Sopenharmony_ci    // Make sure that the registers are all valid, and don't alias each other.
221cb0ef41Sopenharmony_ci    RegList reglist;
231cb0ef41Sopenharmony_ci    for (int i = 0; i < register_parameter_count; ++i) {
241cb0ef41Sopenharmony_ci      Register reg = registers[i];
251cb0ef41Sopenharmony_ci      DCHECK(reg.is_valid());
261cb0ef41Sopenharmony_ci      DCHECK(!reglist.has(reg));
271cb0ef41Sopenharmony_ci      DCHECK_NE(reg, kRootRegister);
281cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
291cb0ef41Sopenharmony_ci      DCHECK_NE(reg, kPtrComprCageBaseRegister);
301cb0ef41Sopenharmony_ci#endif
311cb0ef41Sopenharmony_ci      reglist.set(reg);
321cb0ef41Sopenharmony_ci    }
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci#endif
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  flags_ = flags;
371cb0ef41Sopenharmony_ci  stack_order_ = stack_order;
381cb0ef41Sopenharmony_ci  return_count_ = return_count;
391cb0ef41Sopenharmony_ci  param_count_ = parameter_count;
401cb0ef41Sopenharmony_ci  register_param_count_ = register_parameter_count;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  // The caller owns the the registers array, so we just set the pointer.
431cb0ef41Sopenharmony_ci  register_params_ = registers;
441cb0ef41Sopenharmony_ci}
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_civoid CallInterfaceDescriptorData::InitializeTypes(
471cb0ef41Sopenharmony_ci    const MachineType* machine_types, int machine_types_length) {
481cb0ef41Sopenharmony_ci  DCHECK(IsInitializedRegisters());
491cb0ef41Sopenharmony_ci  const int types_length = return_count_ + param_count_;
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  // Machine types are either fully initialized or null.
521cb0ef41Sopenharmony_ci  if (machine_types == nullptr) {
531cb0ef41Sopenharmony_ci    machine_types_ =
541cb0ef41Sopenharmony_ci        NewArray<MachineType>(types_length, MachineType::AnyTagged());
551cb0ef41Sopenharmony_ci  } else {
561cb0ef41Sopenharmony_ci    DCHECK_EQ(machine_types_length, types_length);
571cb0ef41Sopenharmony_ci    machine_types_ = NewArray<MachineType>(types_length);
581cb0ef41Sopenharmony_ci    for (int i = 0; i < types_length; i++) machine_types_[i] = machine_types[i];
591cb0ef41Sopenharmony_ci  }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  if (!(flags_ & kNoStackScan)) DCHECK(AllStackParametersAreTagged());
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci#ifdef DEBUG
651cb0ef41Sopenharmony_cibool CallInterfaceDescriptorData::AllStackParametersAreTagged() const {
661cb0ef41Sopenharmony_ci  DCHECK(IsInitialized());
671cb0ef41Sopenharmony_ci  const int types_length = return_count_ + param_count_;
681cb0ef41Sopenharmony_ci  const int first_stack_param = return_count_ + register_param_count_;
691cb0ef41Sopenharmony_ci  for (int i = first_stack_param; i < types_length; i++) {
701cb0ef41Sopenharmony_ci    if (!machine_types_[i].IsTagged()) return false;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci  return true;
731cb0ef41Sopenharmony_ci}
741cb0ef41Sopenharmony_ci#endif  // DEBUG
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_civoid CallInterfaceDescriptorData::Reset() {
771cb0ef41Sopenharmony_ci  delete[] machine_types_;
781cb0ef41Sopenharmony_ci  machine_types_ = nullptr;
791cb0ef41Sopenharmony_ci  register_params_ = nullptr;
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci// static
831cb0ef41Sopenharmony_ciCallInterfaceDescriptorData
841cb0ef41Sopenharmony_ci    CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS];
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_civoid CallDescriptors::InitializeOncePerProcess() {
871cb0ef41Sopenharmony_ci#define INTERFACE_DESCRIPTOR(name, ...) \
881cb0ef41Sopenharmony_ci  name##Descriptor().Initialize(&call_descriptor_data_[CallDescriptors::name]);
891cb0ef41Sopenharmony_ci  INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR)
901cb0ef41Sopenharmony_ci#undef INTERFACE_DESCRIPTOR
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  DCHECK(ContextOnlyDescriptor{}.HasContextParameter());
931cb0ef41Sopenharmony_ci  DCHECK(!NoContextDescriptor{}.HasContextParameter());
941cb0ef41Sopenharmony_ci  DCHECK(!AllocateDescriptor{}.HasContextParameter());
951cb0ef41Sopenharmony_ci  DCHECK(!AbortDescriptor{}.HasContextParameter());
961cb0ef41Sopenharmony_ci  DCHECK(!WasmFloat32ToNumberDescriptor{}.HasContextParameter());
971cb0ef41Sopenharmony_ci  DCHECK(!WasmFloat64ToNumberDescriptor{}.HasContextParameter());
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_civoid CallDescriptors::TearDown() {
1011cb0ef41Sopenharmony_ci  for (CallInterfaceDescriptorData& data : call_descriptor_data_) {
1021cb0ef41Sopenharmony_ci    data.Reset();
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciconst char* CallInterfaceDescriptor::DebugName() const {
1071cb0ef41Sopenharmony_ci  CallDescriptors::Key key = CallDescriptors::GetKey(data_);
1081cb0ef41Sopenharmony_ci  switch (key) {
1091cb0ef41Sopenharmony_ci#define DEF_CASE(name, ...)   \
1101cb0ef41Sopenharmony_ci  case CallDescriptors::name: \
1111cb0ef41Sopenharmony_ci    return #name " Descriptor";
1121cb0ef41Sopenharmony_ci    INTERFACE_DESCRIPTOR_LIST(DEF_CASE)
1131cb0ef41Sopenharmony_ci#undef DEF_CASE
1141cb0ef41Sopenharmony_ci    case CallDescriptors::NUMBER_OF_DESCRIPTORS:
1151cb0ef41Sopenharmony_ci      break;
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci  return "";
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_cibool CallInterfaceDescriptor::IsValidFloatParameterRegister(Register reg) {
1211cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)
1221cb0ef41Sopenharmony_ci  return reg.code() % 2 == 0;
1231cb0ef41Sopenharmony_ci#else
1241cb0ef41Sopenharmony_ci  return true;
1251cb0ef41Sopenharmony_ci#endif
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci#if DEBUG
1291cb0ef41Sopenharmony_citemplate <typename DerivedDescriptor>
1301cb0ef41Sopenharmony_civoid StaticCallInterfaceDescriptor<DerivedDescriptor>::Verify(
1311cb0ef41Sopenharmony_ci    CallInterfaceDescriptorData* data) {}
1321cb0ef41Sopenharmony_ci// static
1331cb0ef41Sopenharmony_civoid WriteBarrierDescriptor::Verify(CallInterfaceDescriptorData* data) {
1341cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(ObjectRegister(), SlotAddressRegister(), ValueRegister()));
1351cb0ef41Sopenharmony_ci  // The default parameters should not clobber vital registers in order to
1361cb0ef41Sopenharmony_ci  // reduce code size:
1371cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(ObjectRegister(), kContextRegister,
1381cb0ef41Sopenharmony_ci                     kInterpreterAccumulatorRegister));
1391cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(SlotAddressRegister(), kContextRegister,
1401cb0ef41Sopenharmony_ci                     kInterpreterAccumulatorRegister));
1411cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(ValueRegister(), kContextRegister,
1421cb0ef41Sopenharmony_ci                     kInterpreterAccumulatorRegister));
1431cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(SlotAddressRegister(), kJavaScriptCallNewTargetRegister));
1441cb0ef41Sopenharmony_ci  // Coincidental: to make calling from various builtins easier.
1451cb0ef41Sopenharmony_ci  DCHECK_EQ(ObjectRegister(), kJSFunctionRegister);
1461cb0ef41Sopenharmony_ci  // We need a certain set of registers by default:
1471cb0ef41Sopenharmony_ci  RegList allocatable_regs = data->allocatable_registers();
1481cb0ef41Sopenharmony_ci  DCHECK(allocatable_regs.has(kContextRegister));
1491cb0ef41Sopenharmony_ci  DCHECK(allocatable_regs.has(kReturnRegister0));
1501cb0ef41Sopenharmony_ci  VerifyArgumentRegisterCount(data, 4);
1511cb0ef41Sopenharmony_ci}
1521cb0ef41Sopenharmony_ci#endif  // DEBUG
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci}  // namespace internal
1551cb0ef41Sopenharmony_ci}  // namespace v8
156