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 
10 namespace v8 {
11 namespace internal {
12 
InitializeRegisters( Flags flags, int return_count, int parameter_count, StackArgumentOrder stack_order, int register_parameter_count, const Register* registers)13 void 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 
InitializeTypes( const MachineType* machine_types, int machine_types_length)46 void 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
AllStackParametersAreTagged() const65 bool 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 
Reset()76 void CallInterfaceDescriptorData::Reset() {
77   delete[] machine_types_;
78   machine_types_ = nullptr;
79   register_params_ = nullptr;
80 }
81 
82 // static
83 CallInterfaceDescriptorData
84     CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS];
85 
InitializeOncePerProcess()86 void 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 
TearDown()100 void CallDescriptors::TearDown() {
101   for (CallInterfaceDescriptorData& data : call_descriptor_data_) {
102     data.Reset();
103   }
104 }
105 
DebugName() const106 const 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 
IsValidFloatParameterRegister(Register reg)120 bool 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
129 template <typename DerivedDescriptor>
Verify( CallInterfaceDescriptorData* data)130 void StaticCallInterfaceDescriptor<DerivedDescriptor>::Verify(
131     CallInterfaceDescriptorData* data) {}
132 // static
Verify(CallInterfaceDescriptorData* data)133 void 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