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 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 } | 470 } |
471 #endif | 471 #endif |
472 } | 472 } |
473 | 473 |
474 | 474 |
475 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { | 475 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { |
476 deoptimizer->DoComputeOutputFrames(); | 476 deoptimizer->DoComputeOutputFrames(); |
477 } | 477 } |
478 | 478 |
479 | 479 |
480 static Code* FindOptimizedCode(Isolate* isolate, | 480 bool Deoptimizer::TraceEnabledFor(BailoutType type) { |
481 JSFunction* function, | |
482 Deoptimizer::BailoutType type, | |
483 Address from, | |
484 Code* optimized_code) { | |
485 switch (type) { | 481 switch (type) { |
486 case Deoptimizer::EAGER: | 482 case EAGER: |
487 ASSERT(from == NULL); | 483 case LAZY: |
488 return function->code(); | 484 case DEBUGGER: |
489 case Deoptimizer::LAZY: { | 485 return FLAG_trace_deopt; |
490 Code* compiled_code = | 486 case OSR: |
491 isolate->deoptimizer_data()->FindDeoptimizingCode(from); | 487 return FLAG_trace_osr; |
492 return (compiled_code == NULL) | |
493 ? static_cast<Code*>(isolate->heap()->FindCodeObject(from)) | |
494 : compiled_code; | |
495 } | |
496 case Deoptimizer::OSR: { | |
497 // The function has already been optimized and we're transitioning | |
498 // from the unoptimized shared version to the optimized one in the | |
499 // function. The return address (from) points to unoptimized code. | |
500 Code* compiled_code = function->code(); | |
501 ASSERT(compiled_code->kind() == Code::OPTIMIZED_FUNCTION); | |
502 ASSERT(!compiled_code->contains(from)); | |
503 return compiled_code; | |
504 } | |
505 case Deoptimizer::DEBUGGER: | |
506 ASSERT(optimized_code->contains(from)); | |
507 return optimized_code; | |
508 } | 488 } |
509 UNREACHABLE(); | 489 UNREACHABLE(); |
510 return NULL; | 490 return false; |
511 } | 491 } |
512 | 492 |
513 | 493 |
| 494 const char* Deoptimizer::MessageFor(BailoutType type) { |
| 495 switch (type) { |
| 496 case EAGER: |
| 497 case LAZY: |
| 498 return "DEOPT"; |
| 499 case DEBUGGER: |
| 500 return "DEOPT FOR DEBUGGER"; |
| 501 case OSR: |
| 502 return "OSR"; |
| 503 } |
| 504 UNREACHABLE(); |
| 505 return false; |
| 506 } |
| 507 |
| 508 |
514 Deoptimizer::Deoptimizer(Isolate* isolate, | 509 Deoptimizer::Deoptimizer(Isolate* isolate, |
515 JSFunction* function, | 510 JSFunction* function, |
516 BailoutType type, | 511 BailoutType type, |
517 unsigned bailout_id, | 512 unsigned bailout_id, |
518 Address from, | 513 Address from, |
519 int fp_to_sp_delta, | 514 int fp_to_sp_delta, |
520 Code* optimized_code) | 515 Code* optimized_code) |
521 : isolate_(isolate), | 516 : isolate_(isolate), |
522 function_(function), | 517 function_(function), |
523 bailout_id_(bailout_id), | 518 bailout_id_(bailout_id), |
524 bailout_type_(type), | 519 bailout_type_(type), |
525 from_(from), | 520 from_(from), |
526 fp_to_sp_delta_(fp_to_sp_delta), | 521 fp_to_sp_delta_(fp_to_sp_delta), |
527 has_alignment_padding_(0), | 522 has_alignment_padding_(0), |
528 input_(NULL), | 523 input_(NULL), |
529 output_count_(0), | 524 output_count_(0), |
530 jsframe_count_(0), | 525 jsframe_count_(0), |
531 output_(NULL), | 526 output_(NULL), |
532 deferred_arguments_objects_values_(0), | 527 deferred_arguments_objects_values_(0), |
533 deferred_arguments_objects_(0), | 528 deferred_arguments_objects_(0), |
534 deferred_heap_numbers_(0) { | 529 deferred_heap_numbers_(0) { |
535 if (FLAG_trace_deopt && type != OSR) { | 530 // For COMPILED_STUBs called from builtins, the function pointer is a SMI |
536 if (type == DEBUGGER) { | 531 // indicating an internal frame. |
537 PrintF("**** DEOPT FOR DEBUGGER: "); | |
538 } else { | |
539 PrintF("**** DEOPT: "); | |
540 } | |
541 function->PrintName(); | |
542 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | |
543 bailout_id, | |
544 reinterpret_cast<intptr_t>(from), | |
545 fp_to_sp_delta - (2 * kPointerSize)); | |
546 } else if (FLAG_trace_osr && type == OSR) { | |
547 PrintF("**** OSR: "); | |
548 function->PrintName(); | |
549 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | |
550 bailout_id, | |
551 reinterpret_cast<intptr_t>(from), | |
552 fp_to_sp_delta - (2 * kPointerSize)); | |
553 } | |
554 // For COMPILED_STUBs called from builtins, the function pointer | |
555 // is a SMI indicating an internal frame. | |
556 if (function->IsSmi()) { | 532 if (function->IsSmi()) { |
557 function = NULL; | 533 function = NULL; |
558 } | 534 } |
559 if (function != NULL && function->IsOptimized()) { | 535 if (function != NULL && function->IsOptimized()) { |
560 function->shared()->increment_deopt_count(); | 536 function->shared()->increment_deopt_count(); |
561 } | 537 } |
562 compiled_code_ = | 538 compiled_code_ = FindOptimizedCode(function, optimized_code); |
563 FindOptimizedCode(isolate, function, type, from, optimized_code); | 539 if (TraceEnabledFor(type)) Trace(); |
564 if (FLAG_trace_deopt && type == EAGER) { | |
565 compiled_code_->PrintDeoptLocation(bailout_id); | |
566 } | |
567 ASSERT(HEAP->allow_allocation(false)); | 540 ASSERT(HEAP->allow_allocation(false)); |
568 unsigned size = ComputeInputFrameSize(); | 541 unsigned size = ComputeInputFrameSize(); |
569 input_ = new(size) FrameDescription(size, function); | 542 input_ = new(size) FrameDescription(size, function); |
570 input_->SetFrameType(StackFrame::JAVA_SCRIPT); | 543 input_->SetFrameType(StackFrame::JAVA_SCRIPT); |
571 } | 544 } |
572 | 545 |
573 | 546 |
| 547 Code* Deoptimizer::FindOptimizedCode(JSFunction* function, |
| 548 Code* optimized_code) { |
| 549 switch (bailout_type_) { |
| 550 case Deoptimizer::EAGER: |
| 551 ASSERT(from_ == NULL); |
| 552 return function->code(); |
| 553 case Deoptimizer::LAZY: { |
| 554 Code* compiled_code = |
| 555 isolate_->deoptimizer_data()->FindDeoptimizingCode(from_); |
| 556 return (compiled_code == NULL) |
| 557 ? static_cast<Code*>(isolate_->heap()->FindCodeObject(from_)) |
| 558 : compiled_code; |
| 559 } |
| 560 case Deoptimizer::OSR: { |
| 561 // The function has already been optimized and we're transitioning |
| 562 // from the unoptimized shared version to the optimized one in the |
| 563 // function. The return address (from_) points to unoptimized code. |
| 564 Code* compiled_code = function->code(); |
| 565 ASSERT(compiled_code->kind() == Code::OPTIMIZED_FUNCTION); |
| 566 ASSERT(!compiled_code->contains(from_)); |
| 567 return compiled_code; |
| 568 } |
| 569 case Deoptimizer::DEBUGGER: |
| 570 ASSERT(optimized_code->contains(from_)); |
| 571 return optimized_code; |
| 572 } |
| 573 UNREACHABLE(); |
| 574 return NULL; |
| 575 } |
| 576 |
| 577 |
| 578 void Deoptimizer::Trace() { |
| 579 PrintF("**** %s: ", Deoptimizer::MessageFor(bailout_type_)); |
| 580 PrintFunctionName(); |
| 581 PrintF(" at id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
| 582 bailout_id_, |
| 583 reinterpret_cast<intptr_t>(from_), |
| 584 fp_to_sp_delta_ - (2 * kPointerSize)); |
| 585 if (bailout_type_ == EAGER) compiled_code_->PrintDeoptLocation(bailout_id_); |
| 586 } |
| 587 |
| 588 |
| 589 void Deoptimizer::PrintFunctionName() { |
| 590 if (function_->IsJSFunction()) { |
| 591 function_->PrintName(); |
| 592 } else { |
| 593 PrintF("%s", Code::Kind2String(compiled_code_->kind())); |
| 594 } |
| 595 } |
| 596 |
| 597 |
574 Deoptimizer::~Deoptimizer() { | 598 Deoptimizer::~Deoptimizer() { |
575 ASSERT(input_ == NULL && output_ == NULL); | 599 ASSERT(input_ == NULL && output_ == NULL); |
576 } | 600 } |
577 | 601 |
578 | 602 |
579 void Deoptimizer::DeleteFrameDescriptions() { | 603 void Deoptimizer::DeleteFrameDescriptions() { |
580 delete input_; | 604 delete input_; |
581 for (int i = 0; i < output_count_; ++i) { | 605 for (int i = 0; i < output_count_; ++i) { |
582 if (output_[i] != input_) delete output_[i]; | 606 if (output_[i] != input_) delete output_[i]; |
583 } | 607 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 DoComputeOsrOutputFrame(); | 698 DoComputeOsrOutputFrame(); |
675 return; | 699 return; |
676 } | 700 } |
677 | 701 |
678 // Print some helpful diagnostic information. | 702 // Print some helpful diagnostic information. |
679 int64_t start = OS::Ticks(); | 703 int64_t start = OS::Ticks(); |
680 if (FLAG_trace_deopt) { | 704 if (FLAG_trace_deopt) { |
681 PrintF("[deoptimizing%s: begin 0x%08" V8PRIxPTR " ", | 705 PrintF("[deoptimizing%s: begin 0x%08" V8PRIxPTR " ", |
682 (bailout_type_ == LAZY ? " (lazy)" : ""), | 706 (bailout_type_ == LAZY ? " (lazy)" : ""), |
683 reinterpret_cast<intptr_t>(function_)); | 707 reinterpret_cast<intptr_t>(function_)); |
684 function_->PrintName(); | 708 PrintFunctionName(); |
685 PrintF(" @%d]\n", bailout_id_); | 709 PrintF(" @%d]\n", bailout_id_); |
686 } | 710 } |
687 | 711 |
688 // Determine basic deoptimization information. The optimized frame is | 712 // Determine basic deoptimization information. The optimized frame is |
689 // described by the input data. | 713 // described by the input data. |
690 DeoptimizationInputData* input_data = | 714 DeoptimizationInputData* input_data = |
691 DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); | 715 DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); |
692 BailoutId node_id = input_data->AstId(bailout_id_); | 716 BailoutId node_id = input_data->AstId(bailout_id_); |
693 ByteArray* translations = input_data->TranslationByteArray(); | 717 ByteArray* translations = input_data->TranslationByteArray(); |
694 unsigned translation_index = | 718 unsigned translation_index = |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 } | 778 } |
755 } | 779 } |
756 | 780 |
757 // Print some helpful diagnostic information. | 781 // Print some helpful diagnostic information. |
758 if (FLAG_trace_deopt) { | 782 if (FLAG_trace_deopt) { |
759 double ms = static_cast<double>(OS::Ticks() - start) / 1000; | 783 double ms = static_cast<double>(OS::Ticks() - start) / 1000; |
760 int index = output_count_ - 1; // Index of the topmost frame. | 784 int index = output_count_ - 1; // Index of the topmost frame. |
761 JSFunction* function = output_[index]->GetFunction(); | 785 JSFunction* function = output_[index]->GetFunction(); |
762 PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ", | 786 PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ", |
763 reinterpret_cast<intptr_t>(function)); | 787 reinterpret_cast<intptr_t>(function)); |
764 function->PrintName(); | 788 if (function != NULL) function->PrintName(); |
765 PrintF(" => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s," | 789 PrintF(" => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s," |
766 " took %0.3f ms]\n", | 790 " took %0.3f ms]\n", |
767 node_id.ToInt(), | 791 node_id.ToInt(), |
768 output_[index]->GetPc(), | 792 output_[index]->GetPc(), |
769 FullCodeGenerator::State2String( | 793 FullCodeGenerator::State2String( |
770 static_cast<FullCodeGenerator::State>( | 794 static_cast<FullCodeGenerator::State>( |
771 output_[index]->GetState()->value())), | 795 output_[index]->GetState()->value())), |
772 has_alignment_padding_ ? "with padding" : "no padding", | 796 has_alignment_padding_ ? "with padding" : "no padding", |
773 ms); | 797 ms); |
774 } | 798 } |
(...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2087 | 2111 |
2088 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 2112 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
2089 v->VisitPointer(BitCast<Object**>(&function_)); | 2113 v->VisitPointer(BitCast<Object**>(&function_)); |
2090 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 2114 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
2091 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 2115 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
2092 } | 2116 } |
2093 | 2117 |
2094 #endif // ENABLE_DEBUGGER_SUPPORT | 2118 #endif // ENABLE_DEBUGGER_SUPPORT |
2095 | 2119 |
2096 } } // namespace v8::internal | 2120 } } // namespace v8::internal |
OLD | NEW |