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