1 // Copyright 2014 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 #ifndef V8_COMPILER_LINKAGE_IMPL_H_ 6 #define V8_COMPILER_LINKAGE_IMPL_H_ 7 8 namespace v8 { 9 namespace internal { 10 namespace compiler { 11 12 // TODO(titzer): replace uses of int with size_t in LinkageHelper. 13 template <typename LinkageTraits> 14 class LinkageHelper { 15 public: 16 static const RegList kNoCalleeSaved = 0; 17 AddReturnLocations(LocationSignature::Builder * locations)18 static void AddReturnLocations(LocationSignature::Builder* locations) { 19 DCHECK(locations->return_count_ <= 2); 20 if (locations->return_count_ > 0) { 21 locations->AddReturn(regloc(LinkageTraits::ReturnValueReg())); 22 } 23 if (locations->return_count_ > 1) { 24 locations->AddReturn(regloc(LinkageTraits::ReturnValue2Reg())); 25 } 26 } 27 28 // TODO(turbofan): cache call descriptors for JSFunction calls. GetJSCallDescriptor(Zone * zone,int js_parameter_count)29 static CallDescriptor* GetJSCallDescriptor(Zone* zone, 30 int js_parameter_count) { 31 const size_t return_count = 1; 32 const size_t context_count = 1; 33 const size_t parameter_count = js_parameter_count + context_count; 34 35 LocationSignature::Builder locations(zone, return_count, parameter_count); 36 MachineSignature::Builder types(zone, return_count, parameter_count); 37 38 // Add returns. 39 AddReturnLocations(&locations); 40 for (size_t i = 0; i < return_count; i++) { 41 types.AddReturn(kMachAnyTagged); 42 } 43 44 // All parameters to JS calls go on the stack. 45 for (int i = 0; i < js_parameter_count; i++) { 46 int spill_slot_index = i - js_parameter_count; 47 locations.AddParam(stackloc(spill_slot_index)); 48 types.AddParam(kMachAnyTagged); 49 } 50 // Add context. 51 locations.AddParam(regloc(LinkageTraits::ContextReg())); 52 types.AddParam(kMachAnyTagged); 53 54 // The target for JS function calls is the JSFunction object. 55 MachineType target_type = kMachAnyTagged; 56 LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg()); 57 return new (zone) CallDescriptor(CallDescriptor::kCallJSFunction, // kind 58 target_type, // target MachineType 59 target_loc, // target location 60 types.Build(), // machine_sig 61 locations.Build(), // location_sig 62 js_parameter_count, // js_parameter_count 63 Operator::kNoProperties, // properties 64 kNoCalleeSaved, // callee-saved 65 CallDescriptor::kNeedsFrameState, // flags 66 "js-call"); 67 } 68 69 70 // TODO(turbofan): cache call descriptors for runtime calls. GetRuntimeCallDescriptor(Zone * zone,Runtime::FunctionId function_id,int js_parameter_count,Operator::Properties properties)71 static CallDescriptor* GetRuntimeCallDescriptor( 72 Zone* zone, Runtime::FunctionId function_id, int js_parameter_count, 73 Operator::Properties properties) { 74 const size_t function_count = 1; 75 const size_t num_args_count = 1; 76 const size_t context_count = 1; 77 const size_t parameter_count = function_count + 78 static_cast<size_t>(js_parameter_count) + 79 num_args_count + context_count; 80 81 const Runtime::Function* function = Runtime::FunctionForId(function_id); 82 const size_t return_count = static_cast<size_t>(function->result_size); 83 84 LocationSignature::Builder locations(zone, return_count, parameter_count); 85 MachineSignature::Builder types(zone, return_count, parameter_count); 86 87 // Add returns. 88 AddReturnLocations(&locations); 89 for (size_t i = 0; i < return_count; i++) { 90 types.AddReturn(kMachAnyTagged); 91 } 92 93 // All parameters to the runtime call go on the stack. 94 for (int i = 0; i < js_parameter_count; i++) { 95 locations.AddParam(stackloc(i - js_parameter_count)); 96 types.AddParam(kMachAnyTagged); 97 } 98 // Add runtime function itself. 99 locations.AddParam(regloc(LinkageTraits::RuntimeCallFunctionReg())); 100 types.AddParam(kMachAnyTagged); 101 102 // Add runtime call argument count. 103 locations.AddParam(regloc(LinkageTraits::RuntimeCallArgCountReg())); 104 types.AddParam(kMachPtr); 105 106 // Add context. 107 locations.AddParam(regloc(LinkageTraits::ContextReg())); 108 types.AddParam(kMachAnyTagged); 109 110 CallDescriptor::Flags flags = Linkage::NeedsFrameState(function_id) 111 ? CallDescriptor::kNeedsFrameState 112 : CallDescriptor::kNoFlags; 113 114 // The target for runtime calls is a code object. 115 MachineType target_type = kMachAnyTagged; 116 LinkageLocation target_loc = LinkageLocation::AnyRegister(); 117 return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject, // kind 118 target_type, // target MachineType 119 target_loc, // target location 120 types.Build(), // machine_sig 121 locations.Build(), // location_sig 122 js_parameter_count, // js_parameter_count 123 properties, // properties 124 kNoCalleeSaved, // callee-saved 125 flags, // flags 126 function->name); // debug name 127 } 128 129 130 // TODO(turbofan): cache call descriptors for code stub calls. GetStubCallDescriptor(Zone * zone,CallInterfaceDescriptor descriptor,int stack_parameter_count,CallDescriptor::Flags flags)131 static CallDescriptor* GetStubCallDescriptor( 132 Zone* zone, CallInterfaceDescriptor descriptor, int stack_parameter_count, 133 CallDescriptor::Flags flags) { 134 const int register_parameter_count = 135 descriptor.GetEnvironmentParameterCount(); 136 const int js_parameter_count = 137 register_parameter_count + stack_parameter_count; 138 const int context_count = 1; 139 const size_t return_count = 1; 140 const size_t parameter_count = 141 static_cast<size_t>(js_parameter_count + context_count); 142 143 LocationSignature::Builder locations(zone, return_count, parameter_count); 144 MachineSignature::Builder types(zone, return_count, parameter_count); 145 146 // Add return location. 147 AddReturnLocations(&locations); 148 types.AddReturn(kMachAnyTagged); 149 150 // Add parameters in registers and on the stack. 151 for (int i = 0; i < js_parameter_count; i++) { 152 if (i < register_parameter_count) { 153 // The first parameters go in registers. 154 Register reg = descriptor.GetEnvironmentParameterRegister(i); 155 locations.AddParam(regloc(reg)); 156 } else { 157 // The rest of the parameters go on the stack. 158 int stack_slot = i - register_parameter_count - stack_parameter_count; 159 locations.AddParam(stackloc(stack_slot)); 160 } 161 types.AddParam(kMachAnyTagged); 162 } 163 // Add context. 164 locations.AddParam(regloc(LinkageTraits::ContextReg())); 165 types.AddParam(kMachAnyTagged); 166 167 // The target for stub calls is a code object. 168 MachineType target_type = kMachAnyTagged; 169 LinkageLocation target_loc = LinkageLocation::AnyRegister(); 170 return new (zone) CallDescriptor(CallDescriptor::kCallCodeObject, // kind 171 target_type, // target MachineType 172 target_loc, // target location 173 types.Build(), // machine_sig 174 locations.Build(), // location_sig 175 js_parameter_count, // js_parameter_count 176 Operator::kNoProperties, // properties 177 kNoCalleeSaved, // callee-saved registers 178 flags, // flags 179 descriptor.DebugName(zone->isolate())); 180 } 181 GetSimplifiedCDescriptor(Zone * zone,MachineSignature * msig)182 static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone, 183 MachineSignature* msig) { 184 LocationSignature::Builder locations(zone, msig->return_count(), 185 msig->parameter_count()); 186 // Add return location(s). 187 AddReturnLocations(&locations); 188 189 // Add register and/or stack parameter(s). 190 const int parameter_count = static_cast<int>(msig->parameter_count()); 191 for (int i = 0; i < parameter_count; i++) { 192 if (i < LinkageTraits::CRegisterParametersLength()) { 193 locations.AddParam(regloc(LinkageTraits::CRegisterParameter(i))); 194 } else { 195 locations.AddParam(stackloc(-1 - i)); 196 } 197 } 198 199 // The target for C calls is always an address (i.e. machine pointer). 200 MachineType target_type = kMachPtr; 201 LinkageLocation target_loc = LinkageLocation::AnyRegister(); 202 return new (zone) CallDescriptor(CallDescriptor::kCallAddress, // kind 203 target_type, // target MachineType 204 target_loc, // target location 205 msig, // machine_sig 206 locations.Build(), // location_sig 207 0, // js_parameter_count 208 Operator::kNoProperties, // properties 209 LinkageTraits::CCalleeSaveRegisters(), 210 CallDescriptor::kNoFlags, "c-call"); 211 } 212 regloc(Register reg)213 static LinkageLocation regloc(Register reg) { 214 return LinkageLocation(Register::ToAllocationIndex(reg)); 215 } 216 stackloc(int i)217 static LinkageLocation stackloc(int i) { 218 DCHECK_LT(i, 0); 219 return LinkageLocation(i); 220 } 221 }; 222 } // namespace compiler 223 } // namespace internal 224 } // namespace v8 225 226 #endif // V8_COMPILER_LINKAGE_IMPL_H_ 227