OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 #include "src/compiler.h" | 6 #include "src/compiler.h" |
7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
9 #include "src/compiler/node.h" | 9 #include "src/compiler/node.h" |
| 10 #include "src/compiler/osr.h" |
10 #include "src/compiler/pipeline.h" | 11 #include "src/compiler/pipeline.h" |
11 #include "src/scopes.h" | 12 #include "src/scopes.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
15 namespace compiler { | 16 namespace compiler { |
16 | 17 |
| 18 namespace { |
| 19 LinkageLocation regloc(Register reg) { |
| 20 return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg)); |
| 21 } |
| 22 |
| 23 |
| 24 MachineType reptyp(Representation representation) { |
| 25 switch (representation.kind()) { |
| 26 case Representation::kInteger8: |
| 27 return kMachInt8; |
| 28 case Representation::kUInteger8: |
| 29 return kMachUint8; |
| 30 case Representation::kInteger16: |
| 31 return kMachInt16; |
| 32 case Representation::kUInteger16: |
| 33 return kMachUint16; |
| 34 case Representation::kInteger32: |
| 35 return kMachInt32; |
| 36 case Representation::kSmi: |
| 37 case Representation::kTagged: |
| 38 case Representation::kHeapObject: |
| 39 return kMachAnyTagged; |
| 40 case Representation::kDouble: |
| 41 return kMachFloat64; |
| 42 case Representation::kExternal: |
| 43 return kMachPtr; |
| 44 case Representation::kNone: |
| 45 case Representation::kNumRepresentations: |
| 46 break; |
| 47 } |
| 48 UNREACHABLE(); |
| 49 return kMachNone; |
| 50 } |
| 51 } // namespace |
| 52 |
17 | 53 |
18 std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) { | 54 std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) { |
19 switch (k) { | 55 switch (k) { |
20 case CallDescriptor::kCallCodeObject: | 56 case CallDescriptor::kCallCodeObject: |
21 os << "Code"; | 57 os << "Code"; |
22 break; | 58 break; |
23 case CallDescriptor::kCallJSFunction: | 59 case CallDescriptor::kCallJSFunction: |
24 os << "JS"; | 60 os << "JS"; |
25 break; | 61 break; |
26 case CallDescriptor::kCallAddress: | 62 case CallDescriptor::kCallAddress: |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 for (size_t i = 0; i < InputCount(); ++i) { | 276 for (size_t i = 0; i < InputCount(); ++i) { |
241 if (!GetInputLocation(i).IsRegister()) return false; | 277 if (!GetInputLocation(i).IsRegister()) return false; |
242 } | 278 } |
243 for (size_t i = 0; i < ReturnCount(); ++i) { | 279 for (size_t i = 0; i < ReturnCount(); ++i) { |
244 if (!GetReturnLocation(i).IsRegister()) return false; | 280 if (!GetReturnLocation(i).IsRegister()) return false; |
245 } | 281 } |
246 return true; | 282 return true; |
247 } | 283 } |
248 | 284 |
249 | 285 |
250 //============================================================================== | 286 CallDescriptor* Linkage::GetRuntimeCallDescriptor( |
251 // Provide unimplemented methods on unsupported architectures, to at least link. | 287 Zone* zone, Runtime::FunctionId function_id, int js_parameter_count, |
252 //============================================================================== | 288 Operator::Properties properties) { |
253 #if !V8_TURBOFAN_BACKEND | 289 const size_t function_count = 1; |
| 290 const size_t num_args_count = 1; |
| 291 const size_t context_count = 1; |
| 292 const size_t parameter_count = function_count + |
| 293 static_cast<size_t>(js_parameter_count) + |
| 294 num_args_count + context_count; |
| 295 |
| 296 const Runtime::Function* function = Runtime::FunctionForId(function_id); |
| 297 const size_t return_count = static_cast<size_t>(function->result_size); |
| 298 |
| 299 LocationSignature::Builder locations(zone, return_count, parameter_count); |
| 300 MachineSignature::Builder types(zone, return_count, parameter_count); |
| 301 |
| 302 // Add returns. |
| 303 if (locations.return_count_ > 0) { |
| 304 locations.AddReturn(regloc(kReturnRegister0)); |
| 305 } |
| 306 if (locations.return_count_ > 1) { |
| 307 locations.AddReturn(regloc(kReturnRegister1)); |
| 308 } |
| 309 for (size_t i = 0; i < return_count; i++) { |
| 310 types.AddReturn(kMachAnyTagged); |
| 311 } |
| 312 |
| 313 // All parameters to the runtime call go on the stack. |
| 314 for (int i = 0; i < js_parameter_count; i++) { |
| 315 locations.AddParam( |
| 316 LinkageLocation::ForCallerFrameSlot(i - js_parameter_count)); |
| 317 types.AddParam(kMachAnyTagged); |
| 318 } |
| 319 // Add runtime function itself. |
| 320 locations.AddParam(regloc(kRuntimeCallFunctionRegister)); |
| 321 types.AddParam(kMachAnyTagged); |
| 322 |
| 323 // Add runtime call argument count. |
| 324 locations.AddParam(regloc(kRuntimeCallArgCountRegister)); |
| 325 types.AddParam(kMachPtr); |
| 326 |
| 327 // Add context. |
| 328 locations.AddParam(regloc(kContextRegister)); |
| 329 types.AddParam(kMachAnyTagged); |
| 330 |
| 331 CallDescriptor::Flags flags = Linkage::FrameStateInputCount(function_id) > 0 |
| 332 ? CallDescriptor::kNeedsFrameState |
| 333 : CallDescriptor::kNoFlags; |
| 334 |
| 335 // The target for runtime calls is a code object. |
| 336 MachineType target_type = kMachAnyTagged; |
| 337 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); |
| 338 return new (zone) CallDescriptor( // -- |
| 339 CallDescriptor::kCallCodeObject, // kind |
| 340 target_type, // target MachineType |
| 341 target_loc, // target location |
| 342 types.Build(), // machine_sig |
| 343 locations.Build(), // location_sig |
| 344 js_parameter_count, // stack_parameter_count |
| 345 properties, // properties |
| 346 kNoCalleeSaved, // callee-saved |
| 347 kNoCalleeSaved, // callee-saved fp |
| 348 flags, // flags |
| 349 function->name); // debug name |
| 350 } |
| 351 |
| 352 |
254 CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr, | 353 CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr, |
255 int parameter_count, | 354 int js_parameter_count, |
256 CallDescriptor::Flags flags) { | 355 CallDescriptor::Flags flags) { |
257 UNIMPLEMENTED(); | 356 const size_t return_count = 1; |
258 return NULL; | 357 const size_t context_count = 1; |
259 } | 358 const size_t parameter_count = js_parameter_count + context_count; |
260 | 359 |
261 | 360 LocationSignature::Builder locations(zone, return_count, parameter_count); |
262 LinkageLocation Linkage::GetOsrValueLocation(int index) const { | 361 MachineSignature::Builder types(zone, return_count, parameter_count); |
263 UNIMPLEMENTED(); | 362 |
264 return LinkageLocation(-1); // Dummy value | 363 // All JS calls have exactly one return value. |
265 } | 364 locations.AddReturn(regloc(kReturnRegister0)); |
266 | 365 types.AddReturn(kMachAnyTagged); |
267 | 366 |
268 CallDescriptor* Linkage::GetRuntimeCallDescriptor( | 367 // All parameters to JS calls go on the stack. |
269 Zone* zone, Runtime::FunctionId function, int parameter_count, | 368 for (int i = 0; i < js_parameter_count; i++) { |
270 Operator::Properties properties) { | 369 int spill_slot_index = i - js_parameter_count; |
271 UNIMPLEMENTED(); | 370 locations.AddParam(LinkageLocation::ForCallerFrameSlot(spill_slot_index)); |
272 return NULL; | 371 types.AddParam(kMachAnyTagged); |
273 } | 372 } |
274 | 373 // Add context. |
275 | 374 locations.AddParam(regloc(kContextRegister)); |
| 375 types.AddParam(kMachAnyTagged); |
| 376 |
| 377 // The target for JS function calls is the JSFunction object. |
| 378 MachineType target_type = kMachAnyTagged; |
| 379 // TODO(titzer): When entering into an OSR function from unoptimized code, |
| 380 // the JSFunction is not in a register, but it is on the stack in an |
| 381 // unaddressable spill slot. We hack this in the OSR prologue. Fix. |
| 382 LinkageLocation target_loc = regloc(kJSFunctionRegister); |
| 383 return new (zone) CallDescriptor( // -- |
| 384 CallDescriptor::kCallJSFunction, // kind |
| 385 target_type, // target MachineType |
| 386 target_loc, // target location |
| 387 types.Build(), // machine_sig |
| 388 locations.Build(), // location_sig |
| 389 js_parameter_count, // stack_parameter_count |
| 390 Operator::kNoProperties, // properties |
| 391 kNoCalleeSaved, // callee-saved |
| 392 kNoCalleeSaved, // callee-saved fp |
| 393 flags, // flags |
| 394 "js-call"); |
| 395 } |
| 396 |
| 397 |
| 398 CallDescriptor* Linkage::GetInterpreterDispatchDescriptor(Zone* zone) { |
| 399 MachineSignature::Builder types(zone, 0, 3); |
| 400 LocationSignature::Builder locations(zone, 0, 3); |
| 401 |
| 402 // Add registers for fixed parameters passed via interpreter dispatch. |
| 403 STATIC_ASSERT(0 == Linkage::kInterpreterBytecodeOffsetParameter); |
| 404 types.AddParam(kMachIntPtr); |
| 405 locations.AddParam(regloc(kInterpreterBytecodeOffsetRegister)); |
| 406 |
| 407 STATIC_ASSERT(1 == Linkage::kInterpreterBytecodeArrayParameter); |
| 408 types.AddParam(kMachAnyTagged); |
| 409 locations.AddParam(regloc(kInterpreterBytecodeArrayRegister)); |
| 410 |
| 411 STATIC_ASSERT(2 == Linkage::kInterpreterDispatchTableParameter); |
| 412 types.AddParam(kMachPtr); |
| 413 locations.AddParam(regloc(kInterpreterDispatchTableRegister)); |
| 414 |
| 415 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); |
| 416 return new (zone) CallDescriptor( // -- |
| 417 CallDescriptor::kInterpreterDispatch, // kind |
| 418 kMachNone, // target MachineType |
| 419 target_loc, // target location |
| 420 types.Build(), // machine_sig |
| 421 locations.Build(), // location_sig |
| 422 0, // stack_parameter_count |
| 423 Operator::kNoProperties, // properties |
| 424 kNoCalleeSaved, // callee-saved registers |
| 425 kNoCalleeSaved, // callee-saved fp regs |
| 426 CallDescriptor::kSupportsTailCalls, // flags |
| 427 "interpreter-dispatch"); |
| 428 } |
| 429 |
| 430 |
| 431 // TODO(all): Add support for return representations/locations to |
| 432 // CallInterfaceDescriptor. |
| 433 // TODO(turbofan): cache call descriptors for code stub calls. |
276 CallDescriptor* Linkage::GetStubCallDescriptor( | 434 CallDescriptor* Linkage::GetStubCallDescriptor( |
277 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor, | 435 Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor, |
278 int stack_parameter_count, CallDescriptor::Flags flags, | 436 int stack_parameter_count, CallDescriptor::Flags flags, |
279 Operator::Properties properties, MachineType return_type) { | 437 Operator::Properties properties, MachineType return_type) { |
280 UNIMPLEMENTED(); | 438 const int register_parameter_count = descriptor.GetRegisterParameterCount(); |
281 return NULL; | 439 const int js_parameter_count = |
282 } | 440 register_parameter_count + stack_parameter_count; |
283 | 441 const int context_count = 1; |
284 | 442 const size_t return_count = 1; |
285 #endif // !V8_TURBOFAN_BACKEND | 443 const size_t parameter_count = |
| 444 static_cast<size_t>(js_parameter_count + context_count); |
| 445 |
| 446 LocationSignature::Builder locations(zone, return_count, parameter_count); |
| 447 MachineSignature::Builder types(zone, return_count, parameter_count); |
| 448 |
| 449 // Add return location. |
| 450 locations.AddReturn(regloc(kReturnRegister0)); |
| 451 types.AddReturn(return_type); |
| 452 |
| 453 // Add parameters in registers and on the stack. |
| 454 for (int i = 0; i < js_parameter_count; i++) { |
| 455 if (i < register_parameter_count) { |
| 456 // The first parameters go in registers. |
| 457 Register reg = descriptor.GetRegisterParameter(i); |
| 458 Representation rep = |
| 459 RepresentationFromType(descriptor.GetParameterType(i)); |
| 460 locations.AddParam(regloc(reg)); |
| 461 types.AddParam(reptyp(rep)); |
| 462 } else { |
| 463 // The rest of the parameters go on the stack. |
| 464 int stack_slot = i - register_parameter_count - stack_parameter_count; |
| 465 locations.AddParam(LinkageLocation::ForCallerFrameSlot(stack_slot)); |
| 466 types.AddParam(kMachAnyTagged); |
| 467 } |
| 468 } |
| 469 // Add context. |
| 470 locations.AddParam(regloc(kContextRegister)); |
| 471 types.AddParam(kMachAnyTagged); |
| 472 |
| 473 // The target for stub calls is a code object. |
| 474 MachineType target_type = kMachAnyTagged; |
| 475 LinkageLocation target_loc = LinkageLocation::ForAnyRegister(); |
| 476 return new (zone) CallDescriptor( // -- |
| 477 CallDescriptor::kCallCodeObject, // kind |
| 478 target_type, // target MachineType |
| 479 target_loc, // target location |
| 480 types.Build(), // machine_sig |
| 481 locations.Build(), // location_sig |
| 482 stack_parameter_count, // stack_parameter_count |
| 483 properties, // properties |
| 484 kNoCalleeSaved, // callee-saved registers |
| 485 kNoCalleeSaved, // callee-saved fp |
| 486 flags, // flags |
| 487 descriptor.DebugName(isolate)); |
| 488 } |
| 489 |
| 490 |
| 491 LinkageLocation Linkage::GetOsrValueLocation(int index) const { |
| 492 CHECK(incoming_->IsJSFunctionCall()); |
| 493 int parameter_count = static_cast<int>(incoming_->JSParameterCount() - 1); |
| 494 int first_stack_slot = OsrHelper::FirstStackSlotIndex(parameter_count); |
| 495 |
| 496 if (index == kOsrContextSpillSlotIndex) { |
| 497 // Context. Use the parameter location of the context spill slot. |
| 498 // Parameter (arity + 1) is special for the context of the function frame. |
| 499 int context_index = 1 + 1 + parameter_count; // target + receiver + params |
| 500 return incoming_->GetInputLocation(context_index); |
| 501 } else if (index >= first_stack_slot) { |
| 502 // Local variable stored in this (callee) stack. |
| 503 int spill_index = index - first_stack_slot; |
| 504 return LinkageLocation::ForCalleeFrameSlot(spill_index); |
| 505 } else { |
| 506 // Parameter. Use the assigned location from the incoming call descriptor. |
| 507 int parameter_index = 1 + index; // skip index 0, which is the target. |
| 508 return incoming_->GetInputLocation(parameter_index); |
| 509 } |
| 510 } |
286 } // namespace compiler | 511 } // namespace compiler |
287 } // namespace internal | 512 } // namespace internal |
288 } // namespace v8 | 513 } // namespace v8 |
OLD | NEW |