OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 Builtins* builtins = isolate_->builtins(); | 445 Builtins* builtins = isolate_->builtins(); |
446 Code* adaptor_trampoline = | 446 Code* adaptor_trampoline = |
447 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); | 447 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); |
448 uint32_t pc = reinterpret_cast<uint32_t>( | 448 uint32_t pc = reinterpret_cast<uint32_t>( |
449 adaptor_trampoline->instruction_start() + | 449 adaptor_trampoline->instruction_start() + |
450 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); | 450 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); |
451 output_frame->SetPc(pc); | 451 output_frame->SetPc(pc); |
452 } | 452 } |
453 | 453 |
454 | 454 |
455 void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, | 455 void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator, |
456 int frame_index) { | 456 int frame_index) { |
457 // | 457 // |
458 // FROM TO | 458 // FROM TO |
459 // | .... | | .... | | 459 // | .... | | .... | |
460 // +-------------------------+ +-------------------------+ | 460 // +-------------------------+ +-------------------------+ |
461 // | JSFunction continuation | | JSFunction continuation | | 461 // | JSFunction continuation | | JSFunction continuation | |
462 // +-------------------------+ +-------------------------+ | 462 // +-------------------------+ +-------------------------+ |
463 // | | saved frame (fp) | | saved frame (fp) | | 463 // | | saved frame (fp) | | saved frame (fp) | |
464 // | +=========================+<-fp +=========================+<-fp | 464 // | +=========================+<-fp +=========================+<-fp |
465 // | | JSFunction context | | JSFunction context | | 465 // | | JSFunction context | | JSFunction context | |
466 // v +-------------------------+ +-------------------------| | 466 // v +-------------------------+ +-------------------------| |
467 // | COMPILED_STUB marker | | STUB_FAILURE marker | | 467 // | COMPILED_STUB marker | | STUB_FAILURE marker | |
468 // +-------------------------+ +-------------------------+ | 468 // +-------------------------+ +-------------------------+ |
469 // | | | caller args.length_ | | 469 // | | | caller args.arguments_ | |
470 // | ... | +-------------------------+ | 470 // | ... | +-------------------------+ |
471 // | | | caller args.arguments_ | | 471 // | | | caller args.length_ | |
472 // |-------------------------|<-sp +-------------------------+ | 472 // |-------------------------|<-sp +-------------------------+ |
473 // | caller args pointer | | 473 // | caller args pointer | |
474 // +-------------------------+ | 474 // +-------------------------+ |
475 // | caller stack param 1 | | 475 // | caller stack param 1 | |
476 // parameters in registers +-------------------------+ | 476 // parameters in registers +-------------------------+ |
477 // and spilled to stack | .... | | 477 // and spilled to stack | .... | |
478 // +-------------------------+ | 478 // +-------------------------+ |
479 // | caller stack param n | | 479 // | caller stack param n | |
480 // +-------------------------+<-sp | 480 // +-------------------------+<-sp |
481 // r0 = number of parameters | 481 // r0 = number of parameters |
482 // r1 = failure handler address | 482 // r1 = failure handler address |
483 // fp = saved frame | 483 // fp = saved frame |
484 // cp = JSFunction context | 484 // cp = JSFunction context |
485 // | 485 // |
486 | 486 |
487 ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); | 487 ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); |
488 int major_key = compiled_code_->major_key(); | 488 int major_key = compiled_code_->major_key(); |
489 CodeStubInterfaceDescriptor* descriptor = | 489 CodeStubInterfaceDescriptor* descriptor = |
490 isolate_->code_stub_interface_descriptor(major_key); | 490 isolate_->code_stub_interface_descriptor(major_key); |
491 | 491 |
492 // The output frame must have room for all pushed register parameters | 492 // The output frame must have room for all pushed register parameters |
493 // and the standard stack frame slots. | 493 // and the standard stack frame slots. Include space for an argument |
494 int output_frame_size = StandardFrameConstants::kFixedFrameSize + | 494 // object to the callee and optionally the space to pass the argument |
495 kPointerSize * descriptor->register_param_count_; | 495 // object to the stub failure handler. |
| 496 int height_in_bytes = kPointerSize * descriptor->register_param_count_ + |
| 497 sizeof(Arguments) + kPointerSize; |
| 498 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; |
| 499 int input_frame_size = input_->GetFrameSize(); |
| 500 int output_frame_size = height_in_bytes + fixed_frame_size; |
| 501 if (trace_) { |
| 502 PrintF(" translating %s => StubFailureTrampolineStub, height=%d\n", |
| 503 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key), false), |
| 504 height_in_bytes); |
| 505 } |
496 | 506 |
497 // Include space for an argument object to the callee and optionally | 507 // The stub failure trampoline is a single frame. |
498 // the space to pass the argument object to the stub failure handler. | |
499 output_frame_size += sizeof(Arguments) + kPointerSize; | |
500 | |
501 FrameDescription* output_frame = | 508 FrameDescription* output_frame = |
502 new(output_frame_size) FrameDescription(output_frame_size, 0); | 509 new(output_frame_size) FrameDescription(output_frame_size, NULL); |
| 510 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE); |
503 ASSERT(frame_index == 0); | 511 ASSERT(frame_index == 0); |
504 output_[frame_index] = output_frame; | 512 output_[frame_index] = output_frame; |
505 Code* notify_failure = | |
506 isolate_->builtins()->builtin(Builtins::kNotifyStubFailure); | |
507 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | |
508 output_frame->SetContinuation( | |
509 reinterpret_cast<intptr_t>(notify_failure->entry())); | |
510 | 513 |
511 Code* trampoline = NULL; | 514 // The top address for the output frame can be computed from the input |
512 int extra = descriptor->extra_expression_stack_count_; | 515 // frame pointer and the output frame's height. Subtract space for the |
513 StubFailureTrampolineStub(extra).FindCodeInCache(&trampoline, isolate_); | 516 // context and function slots. |
514 ASSERT(trampoline != NULL); | 517 intptr_t top_address = input_->GetRegister(fp.code()) - (2 * kPointerSize) - |
515 output_frame->SetPc(reinterpret_cast<intptr_t>( | 518 height_in_bytes; |
516 trampoline->instruction_start())); | 519 output_frame->SetTop(top_address); |
517 unsigned input_frame_size = input_->GetFrameSize(); | |
518 | 520 |
519 intptr_t frame_ptr = input_->GetRegister(fp.code()); | 521 // Read caller's PC (JSFunction continuation) from the input frame. |
520 | |
521 // JSFunction continuation | |
522 intptr_t input_frame_offset = input_frame_size - kPointerSize; | 522 intptr_t input_frame_offset = input_frame_size - kPointerSize; |
523 intptr_t output_frame_offset = output_frame_size - kPointerSize; | 523 intptr_t output_frame_offset = output_frame_size - kPointerSize; |
524 intptr_t value = input_->GetFrameSlot(input_frame_offset); | 524 intptr_t value = input_->GetFrameSlot(input_frame_offset); |
525 output_frame->SetFrameSlot(output_frame_offset, value); | 525 output_frame->SetFrameSlot(output_frame_offset, value); |
| 526 if (trace_) { |
| 527 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n", |
| 528 top_address + output_frame_offset, output_frame_offset, value); |
| 529 } |
526 | 530 |
527 // saved frame ptr | 531 // Read caller's FP from the input frame, and set this frame's FP. |
528 input_frame_offset -= kPointerSize; | 532 input_frame_offset -= kPointerSize; |
529 value = input_->GetFrameSlot(input_frame_offset); | 533 value = input_->GetFrameSlot(input_frame_offset); |
530 output_frame_offset -= kPointerSize; | 534 output_frame_offset -= kPointerSize; |
531 output_frame->SetFrameSlot(output_frame_offset, value); | 535 output_frame->SetFrameSlot(output_frame_offset, value); |
| 536 intptr_t frame_ptr = input_->GetRegister(fp.code()); |
| 537 output_frame->SetRegister(fp.code(), frame_ptr); |
| 538 output_frame->SetFp(frame_ptr); |
| 539 if (trace_) { |
| 540 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", |
| 541 top_address + output_frame_offset, output_frame_offset, value); |
| 542 } |
532 | 543 |
533 // Restore context | 544 // The context can be gotten from the input frame. |
534 input_frame_offset -= kPointerSize; | 545 input_frame_offset -= kPointerSize; |
535 value = input_->GetFrameSlot(input_frame_offset); | 546 value = input_->GetFrameSlot(input_frame_offset); |
536 output_frame->SetRegister(cp.code(), value); | 547 output_frame->SetRegister(cp.code(), value); |
537 output_frame_offset -= kPointerSize; | 548 output_frame_offset -= kPointerSize; |
538 output_frame->SetFrameSlot(output_frame_offset, value); | 549 output_frame->SetFrameSlot(output_frame_offset, value); |
| 550 if (trace_) { |
| 551 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n", |
| 552 top_address + output_frame_offset, output_frame_offset, value); |
| 553 } |
539 | 554 |
540 // Internal frame markers | 555 // A marker value is used in place of the function. |
541 output_frame_offset -= kPointerSize; | 556 output_frame_offset -= kPointerSize; |
542 value = reinterpret_cast<intptr_t>( | 557 value = reinterpret_cast<intptr_t>( |
543 Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE)); | 558 Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE)); |
544 output_frame->SetFrameSlot(output_frame_offset, value); | 559 output_frame->SetFrameSlot(output_frame_offset, value); |
| 560 if (trace_) { |
| 561 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (stub fail sentinel)\n", |
| 562 top_address + output_frame_offset, output_frame_offset, value); |
| 563 } |
545 | 564 |
546 int caller_arg_count = 0; | 565 int caller_arg_count = 0; |
547 if (descriptor->stack_parameter_count_ != NULL) { | 566 if (descriptor->stack_parameter_count_ != NULL) { |
548 caller_arg_count = | 567 caller_arg_count = |
549 input_->GetRegister(descriptor->stack_parameter_count_->code()); | 568 input_->GetRegister(descriptor->stack_parameter_count_->code()); |
550 } | 569 } |
551 | 570 |
552 // Build the Arguments object for the caller's parameters and a pointer to it. | 571 // Build the Arguments object for the caller's parameters and a pointer to it. |
553 output_frame_offset -= kPointerSize; | 572 output_frame_offset -= kPointerSize; |
554 value = frame_ptr + StandardFrameConstants::kCallerSPOffset + | 573 value = frame_ptr + StandardFrameConstants::kCallerSPOffset + |
555 (caller_arg_count - 1) * kPointerSize; | 574 (caller_arg_count - 1) * kPointerSize; |
556 output_frame->SetFrameSlot(output_frame_offset, value); | 575 output_frame->SetFrameSlot(output_frame_offset, value); |
| 576 if (trace_) { |
| 577 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; args.arguments\n", |
| 578 top_address + output_frame_offset, output_frame_offset, value); |
| 579 } |
557 | 580 |
| 581 output_frame_offset -= kPointerSize; |
| 582 value = caller_arg_count; |
558 output_frame->SetFrameSlot(output_frame_offset, value); | 583 output_frame->SetFrameSlot(output_frame_offset, value); |
| 584 if (trace_) { |
| 585 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; args.length\n", |
| 586 top_address + output_frame_offset, output_frame_offset, value); |
| 587 } |
| 588 |
559 output_frame_offset -= kPointerSize; | 589 output_frame_offset -= kPointerSize; |
560 output_frame->SetFrameSlot(output_frame_offset, caller_arg_count); | |
561 | |
562 value = frame_ptr - (output_frame_size - output_frame_offset) - | 590 value = frame_ptr - (output_frame_size - output_frame_offset) - |
563 StandardFrameConstants::kMarkerOffset; | 591 StandardFrameConstants::kMarkerOffset + kPointerSize; |
564 output_frame_offset -= kPointerSize; | |
565 output_frame->SetFrameSlot(output_frame_offset, value); | 592 output_frame->SetFrameSlot(output_frame_offset, value); |
| 593 if (trace_) { |
| 594 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; args*\n", |
| 595 top_address + output_frame_offset, output_frame_offset, value); |
| 596 } |
566 | 597 |
567 // Copy the register parameters to the failure frame. | 598 // Copy the register parameters to the failure frame. |
568 for (int i = 0; i < descriptor->register_param_count_; ++i) { | 599 for (int i = 0; i < descriptor->register_param_count_; ++i) { |
569 output_frame_offset -= kPointerSize; | 600 output_frame_offset -= kPointerSize; |
570 DoTranslateCommand(iterator, 0, output_frame_offset); | 601 DoTranslateCommand(iterator, 0, output_frame_offset); |
571 } | 602 } |
572 | 603 |
| 604 ASSERT(0 == output_frame_offset); |
| 605 |
573 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) { | 606 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) { |
574 double double_value = input_->GetDoubleRegister(i); | 607 double double_value = input_->GetDoubleRegister(i); |
575 output_frame->SetDoubleRegister(i, double_value); | 608 output_frame->SetDoubleRegister(i, double_value); |
576 } | 609 } |
577 | 610 |
578 output_frame->SetRegister(fp.code(), frame_ptr); | |
579 output_frame->SetFp(frame_ptr); | |
580 | |
581 ApiFunction function(descriptor->deoptimization_handler_); | 611 ApiFunction function(descriptor->deoptimization_handler_); |
582 ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_); | 612 ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_); |
583 intptr_t handler = reinterpret_cast<intptr_t>(xref.address()); | 613 intptr_t handler = reinterpret_cast<intptr_t>(xref.address()); |
584 int params = descriptor->register_param_count_; | 614 int params = descriptor->register_param_count_; |
585 if (descriptor->stack_parameter_count_ != NULL) { | 615 if (descriptor->stack_parameter_count_ != NULL) { |
586 params++; | 616 params++; |
587 } | 617 } |
588 output_frame->SetRegister(r0.code(), params); | 618 output_frame->SetRegister(r0.code(), params); |
589 output_frame->SetRegister(r1.code(), handler); | 619 output_frame->SetRegister(r1.code(), handler); |
| 620 |
| 621 // Compute this frame's PC, state, and continuation. |
| 622 Code* trampoline = NULL; |
| 623 int extra = descriptor->extra_expression_stack_count_; |
| 624 StubFailureTrampolineStub(extra).FindCodeInCache(&trampoline, isolate_); |
| 625 ASSERT(trampoline != NULL); |
| 626 output_frame->SetPc(reinterpret_cast<intptr_t>( |
| 627 trampoline->instruction_start())); |
| 628 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
| 629 Code* notify_failure = |
| 630 isolate_->builtins()->builtin(Builtins::kNotifyStubFailure); |
| 631 output_frame->SetContinuation( |
| 632 reinterpret_cast<intptr_t>(notify_failure->entry())); |
590 } | 633 } |
591 | 634 |
592 | 635 |
593 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, | 636 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, |
594 int frame_index) { | 637 int frame_index) { |
595 Builtins* builtins = isolate_->builtins(); | 638 Builtins* builtins = isolate_->builtins(); |
596 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 639 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
597 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 640 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
598 unsigned height = iterator->Next(); | 641 unsigned height = iterator->Next(); |
599 unsigned height_in_bytes = height * kPointerSize; | 642 unsigned height_in_bytes = height * kPointerSize; |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 __ push(ip); | 1311 __ push(ip); |
1269 __ b(&done); | 1312 __ b(&done); |
1270 ASSERT(masm()->pc_offset() - start == table_entry_size_); | 1313 ASSERT(masm()->pc_offset() - start == table_entry_size_); |
1271 } | 1314 } |
1272 __ bind(&done); | 1315 __ bind(&done); |
1273 } | 1316 } |
1274 | 1317 |
1275 #undef __ | 1318 #undef __ |
1276 | 1319 |
1277 } } // namespace v8::internal | 1320 } } // namespace v8::internal |
OLD | NEW |