| 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 |