1// Copyright 2012 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/codegen/interface-descriptors.h" 6 7#include "src/codegen/interface-descriptors-inl.h" 8#include "src/codegen/macro-assembler.h" 9 10namespace v8 { 11namespace internal { 12 13void CallInterfaceDescriptorData::InitializeRegisters( 14 Flags flags, int return_count, int parameter_count, 15 StackArgumentOrder stack_order, int register_parameter_count, 16 const Register* registers) { 17 DCHECK(!IsInitializedTypes()); 18 19#ifdef DEBUG 20 { 21 // Make sure that the registers are all valid, and don't alias each other. 22 RegList reglist; 23 for (int i = 0; i < register_parameter_count; ++i) { 24 Register reg = registers[i]; 25 DCHECK(reg.is_valid()); 26 DCHECK(!reglist.has(reg)); 27 DCHECK_NE(reg, kRootRegister); 28#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE 29 DCHECK_NE(reg, kPtrComprCageBaseRegister); 30#endif 31 reglist.set(reg); 32 } 33 } 34#endif 35 36 flags_ = flags; 37 stack_order_ = stack_order; 38 return_count_ = return_count; 39 param_count_ = parameter_count; 40 register_param_count_ = register_parameter_count; 41 42 // The caller owns the the registers array, so we just set the pointer. 43 register_params_ = registers; 44} 45 46void CallInterfaceDescriptorData::InitializeTypes( 47 const MachineType* machine_types, int machine_types_length) { 48 DCHECK(IsInitializedRegisters()); 49 const int types_length = return_count_ + param_count_; 50 51 // Machine types are either fully initialized or null. 52 if (machine_types == nullptr) { 53 machine_types_ = 54 NewArray<MachineType>(types_length, MachineType::AnyTagged()); 55 } else { 56 DCHECK_EQ(machine_types_length, types_length); 57 machine_types_ = NewArray<MachineType>(types_length); 58 for (int i = 0; i < types_length; i++) machine_types_[i] = machine_types[i]; 59 } 60 61 if (!(flags_ & kNoStackScan)) DCHECK(AllStackParametersAreTagged()); 62} 63 64#ifdef DEBUG 65bool CallInterfaceDescriptorData::AllStackParametersAreTagged() const { 66 DCHECK(IsInitialized()); 67 const int types_length = return_count_ + param_count_; 68 const int first_stack_param = return_count_ + register_param_count_; 69 for (int i = first_stack_param; i < types_length; i++) { 70 if (!machine_types_[i].IsTagged()) return false; 71 } 72 return true; 73} 74#endif // DEBUG 75 76void CallInterfaceDescriptorData::Reset() { 77 delete[] machine_types_; 78 machine_types_ = nullptr; 79 register_params_ = nullptr; 80} 81 82// static 83CallInterfaceDescriptorData 84 CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS]; 85 86void CallDescriptors::InitializeOncePerProcess() { 87#define INTERFACE_DESCRIPTOR(name, ...) \ 88 name##Descriptor().Initialize(&call_descriptor_data_[CallDescriptors::name]); 89 INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR) 90#undef INTERFACE_DESCRIPTOR 91 92 DCHECK(ContextOnlyDescriptor{}.HasContextParameter()); 93 DCHECK(!NoContextDescriptor{}.HasContextParameter()); 94 DCHECK(!AllocateDescriptor{}.HasContextParameter()); 95 DCHECK(!AbortDescriptor{}.HasContextParameter()); 96 DCHECK(!WasmFloat32ToNumberDescriptor{}.HasContextParameter()); 97 DCHECK(!WasmFloat64ToNumberDescriptor{}.HasContextParameter()); 98} 99 100void CallDescriptors::TearDown() { 101 for (CallInterfaceDescriptorData& data : call_descriptor_data_) { 102 data.Reset(); 103 } 104} 105 106const char* CallInterfaceDescriptor::DebugName() const { 107 CallDescriptors::Key key = CallDescriptors::GetKey(data_); 108 switch (key) { 109#define DEF_CASE(name, ...) \ 110 case CallDescriptors::name: \ 111 return #name " Descriptor"; 112 INTERFACE_DESCRIPTOR_LIST(DEF_CASE) 113#undef DEF_CASE 114 case CallDescriptors::NUMBER_OF_DESCRIPTORS: 115 break; 116 } 117 return ""; 118} 119 120bool CallInterfaceDescriptor::IsValidFloatParameterRegister(Register reg) { 121#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) 122 return reg.code() % 2 == 0; 123#else 124 return true; 125#endif 126} 127 128#if DEBUG 129template <typename DerivedDescriptor> 130void StaticCallInterfaceDescriptor<DerivedDescriptor>::Verify( 131 CallInterfaceDescriptorData* data) {} 132// static 133void WriteBarrierDescriptor::Verify(CallInterfaceDescriptorData* data) { 134 DCHECK(!AreAliased(ObjectRegister(), SlotAddressRegister(), ValueRegister())); 135 // The default parameters should not clobber vital registers in order to 136 // reduce code size: 137 DCHECK(!AreAliased(ObjectRegister(), kContextRegister, 138 kInterpreterAccumulatorRegister)); 139 DCHECK(!AreAliased(SlotAddressRegister(), kContextRegister, 140 kInterpreterAccumulatorRegister)); 141 DCHECK(!AreAliased(ValueRegister(), kContextRegister, 142 kInterpreterAccumulatorRegister)); 143 DCHECK(!AreAliased(SlotAddressRegister(), kJavaScriptCallNewTargetRegister)); 144 // Coincidental: to make calling from various builtins easier. 145 DCHECK_EQ(ObjectRegister(), kJSFunctionRegister); 146 // We need a certain set of registers by default: 147 RegList allocatable_regs = data->allocatable_registers(); 148 DCHECK(allocatable_regs.has(kContextRegister)); 149 DCHECK(allocatable_regs.has(kReturnRegister0)); 150 VerifyArgumentRegisterCount(data, 4); 151} 152#endif // DEBUG 153 154} // namespace internal 155} // namespace v8 156