| OLD | NEW |
| (Empty) |
| 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 #include "src/code-stubs.h" | |
| 9 #include "src/compiler/osr.h" | |
| 10 | |
| 11 namespace v8 { | |
| 12 namespace internal { | |
| 13 namespace compiler { | |
| 14 | |
| 15 // TODO(titzer): replace uses of int with size_t in LinkageHelper. | |
| 16 template <typename LinkageTraits> | |
| 17 class LinkageHelper { | |
| 18 public: | |
| 19 static const RegList kNoCalleeSaved = 0; | |
| 20 | |
| 21 static void AddReturnLocations(LocationSignature::Builder* locations) { | |
| 22 DCHECK(locations->return_count_ <= 2); | |
| 23 if (locations->return_count_ > 0) { | |
| 24 locations->AddReturn(regloc(LinkageTraits::ReturnValueReg())); | |
| 25 } | |
| 26 if (locations->return_count_ > 1) { | |
| 27 locations->AddReturn(regloc(LinkageTraits::ReturnValue2Reg())); | |
| 28 } | |
| 29 } | |
| 30 | |
| 31 // TODO(turbofan): cache call descriptors for JSFunction calls. | |
| 32 static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr, | |
| 33 int js_parameter_count, | |
| 34 CallDescriptor::Flags flags) { | |
| 35 const size_t return_count = 1; | |
| 36 const size_t context_count = 1; | |
| 37 const size_t parameter_count = js_parameter_count + context_count; | |
| 38 | |
| 39 LocationSignature::Builder locations(zone, return_count, parameter_count); | |
| 40 MachineSignature::Builder types(zone, return_count, parameter_count); | |
| 41 | |
| 42 // Add returns. | |
| 43 AddReturnLocations(&locations); | |
| 44 for (size_t i = 0; i < return_count; i++) { | |
| 45 types.AddReturn(kMachAnyTagged); | |
| 46 } | |
| 47 | |
| 48 // All parameters to JS calls go on the stack. | |
| 49 for (int i = 0; i < js_parameter_count; i++) { | |
| 50 int spill_slot_index = i - js_parameter_count; | |
| 51 locations.AddParam(stackloc(spill_slot_index)); | |
| 52 types.AddParam(kMachAnyTagged); | |
| 53 } | |
| 54 // Add context. | |
| 55 locations.AddParam(regloc(LinkageTraits::ContextReg())); | |
| 56 types.AddParam(kMachAnyTagged); | |
| 57 | |
| 58 // The target for JS function calls is the JSFunction object. | |
| 59 MachineType target_type = kMachAnyTagged; | |
| 60 // TODO(titzer): When entering into an OSR function from unoptimized code, | |
| 61 // the JSFunction is not in a register, but it is on the stack in an | |
| 62 // unaddressable spill slot. We hack this in the OSR prologue. Fix. | |
| 63 LinkageLocation target_loc = regloc(LinkageTraits::JSCallFunctionReg()); | |
| 64 return new (zone) CallDescriptor( // -- | |
| 65 CallDescriptor::kCallJSFunction, // kind | |
| 66 target_type, // target MachineType | |
| 67 target_loc, // target location | |
| 68 types.Build(), // machine_sig | |
| 69 locations.Build(), // location_sig | |
| 70 js_parameter_count, // stack_parameter_count | |
| 71 Operator::kNoProperties, // properties | |
| 72 kNoCalleeSaved, // callee-saved | |
| 73 kNoCalleeSaved, // callee-saved fp | |
| 74 flags, // flags | |
| 75 "js-call"); | |
| 76 } | |
| 77 | |
| 78 | |
| 79 // TODO(turbofan): cache call descriptors for runtime calls. | |
| 80 static CallDescriptor* GetRuntimeCallDescriptor( | |
| 81 Zone* zone, Runtime::FunctionId function_id, int js_parameter_count, | |
| 82 Operator::Properties properties) { | |
| 83 const size_t function_count = 1; | |
| 84 const size_t num_args_count = 1; | |
| 85 const size_t context_count = 1; | |
| 86 const size_t parameter_count = function_count + | |
| 87 static_cast<size_t>(js_parameter_count) + | |
| 88 num_args_count + context_count; | |
| 89 | |
| 90 const Runtime::Function* function = Runtime::FunctionForId(function_id); | |
| 91 const size_t return_count = static_cast<size_t>(function->result_size); | |
| 92 | |
| 93 LocationSignature::Builder locations(zone, return_count, parameter_count); | |
| 94 MachineSignature::Builder types(zone, return_count, parameter_count); | |
| 95 | |
| 96 // Add returns. | |
| 97 AddReturnLocations(&locations); | |
| 98 for (size_t i = 0; i < return_count; i++) { | |
| 99 types.AddReturn(kMachAnyTagged); | |
| 100 } | |
| 101 | |
| 102 // All parameters to the runtime call go on the stack. | |
| 103 for (int i = 0; i < js_parameter_count; i++) { | |
| 104 locations.AddParam(stackloc(i - js_parameter_count)); | |
| 105 types.AddParam(kMachAnyTagged); | |
| 106 } | |
| 107 // Add runtime function itself. | |
| 108 locations.AddParam(regloc(LinkageTraits::RuntimeCallFunctionReg())); | |
| 109 types.AddParam(kMachAnyTagged); | |
| 110 | |
| 111 // Add runtime call argument count. | |
| 112 locations.AddParam(regloc(LinkageTraits::RuntimeCallArgCountReg())); | |
| 113 types.AddParam(kMachPtr); | |
| 114 | |
| 115 // Add context. | |
| 116 locations.AddParam(regloc(LinkageTraits::ContextReg())); | |
| 117 types.AddParam(kMachAnyTagged); | |
| 118 | |
| 119 CallDescriptor::Flags flags = Linkage::FrameStateInputCount(function_id) > 0 | |
| 120 ? CallDescriptor::kNeedsFrameState | |
| 121 : CallDescriptor::kNoFlags; | |
| 122 | |
| 123 // The target for runtime calls is a code object. | |
| 124 MachineType target_type = kMachAnyTagged; | |
| 125 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); | |
| 126 return new (zone) CallDescriptor( // -- | |
| 127 CallDescriptor::kCallCodeObject, // kind | |
| 128 target_type, // target MachineType | |
| 129 target_loc, // target location | |
| 130 types.Build(), // machine_sig | |
| 131 locations.Build(), // location_sig | |
| 132 js_parameter_count, // stack_parameter_count | |
| 133 properties, // properties | |
| 134 kNoCalleeSaved, // callee-saved | |
| 135 kNoCalleeSaved, // callee-saved fp | |
| 136 flags, // flags | |
| 137 function->name); // debug name | |
| 138 } | |
| 139 | |
| 140 | |
| 141 // TODO(all): Add support for return representations/locations to | |
| 142 // CallInterfaceDescriptor. | |
| 143 // TODO(turbofan): cache call descriptors for code stub calls. | |
| 144 static CallDescriptor* GetStubCallDescriptor( | |
| 145 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor, | |
| 146 int stack_parameter_count, CallDescriptor::Flags flags, | |
| 147 Operator::Properties properties, MachineType return_type) { | |
| 148 const int register_parameter_count = descriptor.GetRegisterParameterCount(); | |
| 149 const int js_parameter_count = | |
| 150 register_parameter_count + stack_parameter_count; | |
| 151 const int context_count = 1; | |
| 152 const size_t return_count = 1; | |
| 153 const size_t parameter_count = | |
| 154 static_cast<size_t>(js_parameter_count + context_count); | |
| 155 | |
| 156 LocationSignature::Builder locations(zone, return_count, parameter_count); | |
| 157 MachineSignature::Builder types(zone, return_count, parameter_count); | |
| 158 | |
| 159 // Add return location. | |
| 160 AddReturnLocations(&locations); | |
| 161 types.AddReturn(return_type); | |
| 162 | |
| 163 // Add parameters in registers and on the stack. | |
| 164 for (int i = 0; i < js_parameter_count; i++) { | |
| 165 if (i < register_parameter_count) { | |
| 166 // The first parameters go in registers. | |
| 167 Register reg = descriptor.GetRegisterParameter(i); | |
| 168 Representation rep = | |
| 169 RepresentationFromType(descriptor.GetParameterType(i)); | |
| 170 locations.AddParam(regloc(reg)); | |
| 171 types.AddParam(reptyp(rep)); | |
| 172 } else { | |
| 173 // The rest of the parameters go on the stack. | |
| 174 int stack_slot = i - register_parameter_count - stack_parameter_count; | |
| 175 locations.AddParam(stackloc(stack_slot)); | |
| 176 types.AddParam(kMachAnyTagged); | |
| 177 } | |
| 178 } | |
| 179 // Add context. | |
| 180 locations.AddParam(regloc(LinkageTraits::ContextReg())); | |
| 181 types.AddParam(kMachAnyTagged); | |
| 182 | |
| 183 // The target for stub calls is a code object. | |
| 184 MachineType target_type = kMachAnyTagged; | |
| 185 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); | |
| 186 return new (zone) CallDescriptor( // -- | |
| 187 CallDescriptor::kCallCodeObject, // kind | |
| 188 target_type, // target MachineType | |
| 189 target_loc, // target location | |
| 190 types.Build(), // machine_sig | |
| 191 locations.Build(), // location_sig | |
| 192 stack_parameter_count, // stack_parameter_count | |
| 193 properties, // properties | |
| 194 kNoCalleeSaved, // callee-saved registers | |
| 195 kNoCalleeSaved, // callee-saved fp | |
| 196 flags, // flags | |
| 197 descriptor.DebugName(isolate)); | |
| 198 } | |
| 199 | |
| 200 static CallDescriptor* GetInterpreterDispatchDescriptor(Zone* zone) { | |
| 201 MachineSignature::Builder types(zone, 0, 3); | |
| 202 LocationSignature::Builder locations(zone, 0, 3); | |
| 203 | |
| 204 // Add registers for fixed parameters passed via interpreter dispatch. | |
| 205 STATIC_ASSERT(0 == Linkage::kInterpreterBytecodeOffsetParameter); | |
| 206 types.AddParam(kMachIntPtr); | |
| 207 locations.AddParam(regloc(LinkageTraits::InterpreterBytecodeOffsetReg())); | |
| 208 | |
| 209 STATIC_ASSERT(1 == Linkage::kInterpreterBytecodeArrayParameter); | |
| 210 types.AddParam(kMachAnyTagged); | |
| 211 locations.AddParam(regloc(LinkageTraits::InterpreterBytecodeArrayReg())); | |
| 212 | |
| 213 STATIC_ASSERT(2 == Linkage::kInterpreterDispatchTableParameter); | |
| 214 types.AddParam(kMachPtr); | |
| 215 locations.AddParam(regloc(LinkageTraits::InterpreterDispatchTableReg())); | |
| 216 | |
| 217 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); | |
| 218 return new (zone) CallDescriptor( // -- | |
| 219 CallDescriptor::kInterpreterDispatch, // kind | |
| 220 kMachNone, // target MachineType | |
| 221 target_loc, // target location | |
| 222 types.Build(), // machine_sig | |
| 223 locations.Build(), // location_sig | |
| 224 0, // stack_parameter_count | |
| 225 Operator::kNoProperties, // properties | |
| 226 kNoCalleeSaved, // callee-saved registers | |
| 227 kNoCalleeSaved, // callee-saved fp regs | |
| 228 CallDescriptor::kSupportsTailCalls, // flags | |
| 229 "interpreter-dispatch"); | |
| 230 } | |
| 231 | |
| 232 static LinkageLocation regloc(Register reg) { | |
| 233 return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg)); | |
| 234 } | |
| 235 | |
| 236 static LinkageLocation stackloc(int i) { | |
| 237 return LinkageLocation::ForCallerFrameSlot(i); | |
| 238 } | |
| 239 | |
| 240 static MachineType reptyp(Representation representation) { | |
| 241 switch (representation.kind()) { | |
| 242 case Representation::kInteger8: | |
| 243 return kMachInt8; | |
| 244 case Representation::kUInteger8: | |
| 245 return kMachUint8; | |
| 246 case Representation::kInteger16: | |
| 247 return kMachInt16; | |
| 248 case Representation::kUInteger16: | |
| 249 return kMachUint16; | |
| 250 case Representation::kInteger32: | |
| 251 return kMachInt32; | |
| 252 case Representation::kSmi: | |
| 253 case Representation::kTagged: | |
| 254 case Representation::kHeapObject: | |
| 255 return kMachAnyTagged; | |
| 256 case Representation::kDouble: | |
| 257 return kMachFloat64; | |
| 258 case Representation::kExternal: | |
| 259 return kMachPtr; | |
| 260 case Representation::kNone: | |
| 261 case Representation::kNumRepresentations: | |
| 262 break; | |
| 263 } | |
| 264 UNREACHABLE(); | |
| 265 return kMachNone; | |
| 266 } | |
| 267 }; | |
| 268 | |
| 269 | |
| 270 LinkageLocation Linkage::GetOsrValueLocation(int index) const { | |
| 271 CHECK(incoming_->IsJSFunctionCall()); | |
| 272 int parameter_count = static_cast<int>(incoming_->JSParameterCount() - 1); | |
| 273 int first_stack_slot = OsrHelper::FirstStackSlotIndex(parameter_count); | |
| 274 | |
| 275 if (index == kOsrContextSpillSlotIndex) { | |
| 276 // Context. Use the parameter location of the context spill slot. | |
| 277 // Parameter (arity + 1) is special for the context of the function frame. | |
| 278 int context_index = 1 + 1 + parameter_count; // target + receiver + params | |
| 279 return incoming_->GetInputLocation(context_index); | |
| 280 } else if (index >= first_stack_slot) { | |
| 281 // Local variable stored in this (callee) stack. | |
| 282 int spill_index = index - first_stack_slot; | |
| 283 return LinkageLocation::ForCalleeFrameSlot(spill_index); | |
| 284 } else { | |
| 285 // Parameter. Use the assigned location from the incoming call descriptor. | |
| 286 int parameter_index = 1 + index; // skip index 0, which is the target. | |
| 287 return incoming_->GetInputLocation(parameter_index); | |
| 288 } | |
| 289 } | |
| 290 | |
| 291 } // namespace compiler | |
| 292 } // namespace internal | |
| 293 } // namespace v8 | |
| 294 | |
| 295 #endif // V8_COMPILER_LINKAGE_IMPL_H_ | |
| OLD | NEW |