OLD | NEW |
---|---|
1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
97 | 97 |
98 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { | 98 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
99 ASSERT(isolate == Isolate::Current()); | 99 ASSERT(isolate == Isolate::Current()); |
100 Deoptimizer* result = isolate->deoptimizer_data()->current_; | 100 Deoptimizer* result = isolate->deoptimizer_data()->current_; |
101 ASSERT(result != NULL); | 101 ASSERT(result != NULL); |
102 result->DeleteFrameDescriptions(); | 102 result->DeleteFrameDescriptions(); |
103 isolate->deoptimizer_data()->current_ = NULL; | 103 isolate->deoptimizer_data()->current_ = NULL; |
104 return result; | 104 return result; |
105 } | 105 } |
106 | 106 |
107 | |
108 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { | |
109 if (jsframe_index == 0) return 0; | |
110 | |
111 int frame_index = 0; | |
112 while (jsframe_index >= 0) { | |
113 FrameDescription* frame = output_[frame_index]; | |
114 if (frame->GetType() == StackFrame::JAVA_SCRIPT) { | |
115 jsframe_index--; | |
116 } | |
117 frame_index++; | |
118 } | |
119 | |
120 return frame_index - 1; | |
121 } | |
122 | |
123 | |
107 #ifdef ENABLE_DEBUGGER_SUPPORT | 124 #ifdef ENABLE_DEBUGGER_SUPPORT |
108 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | 125 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
109 JavaScriptFrame* frame, | 126 JavaScriptFrame* frame, |
110 int frame_index, | 127 int jsframe_index, |
111 Isolate* isolate) { | 128 Isolate* isolate) { |
112 ASSERT(isolate == Isolate::Current()); | 129 ASSERT(isolate == Isolate::Current()); |
113 ASSERT(frame->is_optimized()); | 130 ASSERT(frame->is_optimized()); |
114 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); | 131 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); |
115 | 132 |
116 // Get the function and code from the frame. | 133 // Get the function and code from the frame. |
117 JSFunction* function = JSFunction::cast(frame->function()); | 134 JSFunction* function = JSFunction::cast(frame->function()); |
118 Code* code = frame->LookupCode(); | 135 Code* code = frame->LookupCode(); |
119 | 136 |
120 // Locate the deoptimization point in the code. As we are at a call the | 137 // Locate the deoptimization point in the code. As we are at a call the |
(...skipping 15 matching lines...) Expand all Loading... | |
136 fp_to_sp_delta, | 153 fp_to_sp_delta, |
137 code); | 154 code); |
138 Address tos = frame->fp() - fp_to_sp_delta; | 155 Address tos = frame->fp() - fp_to_sp_delta; |
139 deoptimizer->FillInputFrame(tos, frame); | 156 deoptimizer->FillInputFrame(tos, frame); |
140 | 157 |
141 // Calculate the output frames. | 158 // Calculate the output frames. |
142 Deoptimizer::ComputeOutputFrames(deoptimizer); | 159 Deoptimizer::ComputeOutputFrames(deoptimizer); |
143 | 160 |
144 // Create the GC safe output frame information and register it for GC | 161 // Create the GC safe output frame information and register it for GC |
145 // handling. | 162 // handling. |
146 ASSERT_LT(frame_index, deoptimizer->output_count()); | 163 ASSERT_LT(jsframe_index, deoptimizer->jsframe_count()); |
164 | |
165 // Convert JS frame index into frame index. | |
166 int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index); | |
167 | |
168 bool has_arguments_adaptor = | |
169 frame_index > 0 && | |
170 deoptimizer->output_[frame_index - 1]->GetType() == | |
171 StackFrame::ARGUMENTS_ADAPTOR; | |
172 | |
147 DeoptimizedFrameInfo* info = | 173 DeoptimizedFrameInfo* info = |
148 new DeoptimizedFrameInfo(deoptimizer, frame_index); | 174 new DeoptimizedFrameInfo(deoptimizer, frame_index, has_arguments_adaptor); |
149 isolate->deoptimizer_data()->deoptimized_frame_info_ = info; | 175 isolate->deoptimizer_data()->deoptimized_frame_info_ = info; |
150 | 176 |
151 // Get the "simulated" top and size for the requested frame. | 177 // Get the "simulated" top and size for the requested frame. |
152 Address top = | 178 FrameDescription* parameters_frame = |
153 reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop()); | 179 deoptimizer->output_[ |
154 uint32_t size = deoptimizer->output_[frame_index]->GetFrameSize(); | 180 has_arguments_adaptor ? (frame_index - 1) : frame_index]; |
181 | |
182 uint32_t parameters_size = (info->parameters_count() + 1) * kPointerSize; | |
183 Address parameters_top = reinterpret_cast<Address>( | |
184 parameters_frame->GetTop() + (parameters_frame->GetFrameSize() - | |
185 parameters_size)); | |
186 | |
187 uint32_t expressions_size = info->expression_count() * kPointerSize; | |
188 Address expressions_top = reinterpret_cast<Address>( | |
189 deoptimizer->output_[frame_index]->GetTop()); | |
155 | 190 |
156 // Done with the GC-unsafe frame descriptions. This re-enables allocation. | 191 // Done with the GC-unsafe frame descriptions. This re-enables allocation. |
157 deoptimizer->DeleteFrameDescriptions(); | 192 deoptimizer->DeleteFrameDescriptions(); |
158 | 193 |
159 // Allocate a heap number for the doubles belonging to this frame. | 194 // Allocate a heap number for the doubles belonging to this frame. |
160 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( | 195 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( |
161 top, size, info); | 196 parameters_top, parameters_size, expressions_top, expressions_size, info); |
162 | 197 |
163 // Finished using the deoptimizer instance. | 198 // Finished using the deoptimizer instance. |
164 delete deoptimizer; | 199 delete deoptimizer; |
165 | 200 |
166 return info; | 201 return info; |
167 } | 202 } |
168 | 203 |
169 | 204 |
170 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | 205 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
171 Isolate* isolate) { | 206 Isolate* isolate) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 int fp_to_sp_delta, | 341 int fp_to_sp_delta, |
307 Code* optimized_code) | 342 Code* optimized_code) |
308 : isolate_(isolate), | 343 : isolate_(isolate), |
309 function_(function), | 344 function_(function), |
310 bailout_id_(bailout_id), | 345 bailout_id_(bailout_id), |
311 bailout_type_(type), | 346 bailout_type_(type), |
312 from_(from), | 347 from_(from), |
313 fp_to_sp_delta_(fp_to_sp_delta), | 348 fp_to_sp_delta_(fp_to_sp_delta), |
314 input_(NULL), | 349 input_(NULL), |
315 output_count_(0), | 350 output_count_(0), |
351 jsframe_count_(0), | |
316 output_(NULL), | 352 output_(NULL), |
317 frame_alignment_marker_(isolate->heap()->frame_alignment_marker()), | 353 frame_alignment_marker_(isolate->heap()->frame_alignment_marker()), |
318 has_alignment_padding_(0), | 354 has_alignment_padding_(0), |
319 deferred_heap_numbers_(0) { | 355 deferred_heap_numbers_(0) { |
320 if (FLAG_trace_deopt && type != OSR) { | 356 if (FLAG_trace_deopt && type != OSR) { |
321 if (type == DEBUGGER) { | 357 if (type == DEBUGGER) { |
322 PrintF("**** DEOPT FOR DEBUGGER: "); | 358 PrintF("**** DEOPT FOR DEBUGGER: "); |
323 } else { | 359 } else { |
324 PrintF("**** DEOPT: "); | 360 PrintF("**** DEOPT: "); |
325 } | 361 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 } else if (type == DEBUGGER) { | 409 } else if (type == DEBUGGER) { |
374 optimized_code_ = optimized_code; | 410 optimized_code_ = optimized_code; |
375 ASSERT(optimized_code_->contains(from)); | 411 ASSERT(optimized_code_->contains(from)); |
376 } | 412 } |
377 ASSERT(HEAP->allow_allocation(false)); | 413 ASSERT(HEAP->allow_allocation(false)); |
378 unsigned size = ComputeInputFrameSize(); | 414 unsigned size = ComputeInputFrameSize(); |
379 input_ = new(size) FrameDescription(size, function); | 415 input_ = new(size) FrameDescription(size, function); |
380 #ifdef DEBUG | 416 #ifdef DEBUG |
381 input_->SetKind(Code::OPTIMIZED_FUNCTION); | 417 input_->SetKind(Code::OPTIMIZED_FUNCTION); |
382 #endif | 418 #endif |
419 input_->SetType(StackFrame::JAVA_SCRIPT); | |
383 } | 420 } |
384 | 421 |
385 | 422 |
386 Deoptimizer::~Deoptimizer() { | 423 Deoptimizer::~Deoptimizer() { |
387 ASSERT(input_ == NULL && output_ == NULL); | 424 ASSERT(input_ == NULL && output_ == NULL); |
388 } | 425 } |
389 | 426 |
390 | 427 |
391 void Deoptimizer::DeleteFrameDescriptions() { | 428 void Deoptimizer::DeleteFrameDescriptions() { |
392 delete input_; | 429 delete input_; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 | 545 |
509 // Do the input frame to output frame(s) translation. | 546 // Do the input frame to output frame(s) translation. |
510 TranslationIterator iterator(translations, translation_index); | 547 TranslationIterator iterator(translations, translation_index); |
511 Translation::Opcode opcode = | 548 Translation::Opcode opcode = |
512 static_cast<Translation::Opcode>(iterator.Next()); | 549 static_cast<Translation::Opcode>(iterator.Next()); |
513 ASSERT(Translation::BEGIN == opcode); | 550 ASSERT(Translation::BEGIN == opcode); |
514 USE(opcode); | 551 USE(opcode); |
515 // Read the number of output frames and allocate an array for their | 552 // Read the number of output frames and allocate an array for their |
516 // descriptions. | 553 // descriptions. |
517 int count = iterator.Next(); | 554 int count = iterator.Next(); |
555 iterator.Next(); // Drop JS frames count. | |
518 ASSERT(output_ == NULL); | 556 ASSERT(output_ == NULL); |
519 output_ = new FrameDescription*[count]; | 557 output_ = new FrameDescription*[count]; |
520 for (int i = 0; i < count; ++i) { | 558 for (int i = 0; i < count; ++i) { |
521 output_[i] = NULL; | 559 output_[i] = NULL; |
522 } | 560 } |
523 output_count_ = count; | 561 output_count_ = count; |
524 | 562 |
525 // Translate each output frame. | 563 // Translate each output frame. |
526 for (int i = 0; i < count; ++i) { | 564 for (int i = 0; i < count; ++i) { |
527 DoComputeFrame(&iterator, i); | 565 // Read the ast node id, function, and frame height for this output frame. |
566 Translation::Opcode opcode = | |
567 static_cast<Translation::Opcode>(iterator.Next()); | |
568 switch (opcode) { | |
569 case Translation::JS_FRAME: | |
570 DoComputeJSFrame(&iterator, i); | |
571 jsframe_count_++; | |
572 break; | |
573 case Translation::ARGUMENTS_ADAPTOR_FRAME: | |
574 DoComputeArgumentsAdaptorFrame(&iterator, i); | |
575 break; | |
576 default: | |
577 UNREACHABLE(); | |
578 break; | |
579 } | |
528 } | 580 } |
529 | 581 |
530 // Print some helpful diagnostic information. | 582 // Print some helpful diagnostic information. |
531 if (FLAG_trace_deopt) { | 583 if (FLAG_trace_deopt) { |
532 double ms = static_cast<double>(OS::Ticks() - start) / 1000; | 584 double ms = static_cast<double>(OS::Ticks() - start) / 1000; |
533 int index = output_count_ - 1; // Index of the topmost frame. | 585 int index = output_count_ - 1; // Index of the topmost frame. |
534 JSFunction* function = output_[index]->GetFunction(); | 586 JSFunction* function = output_[index]->GetFunction(); |
535 PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ", | 587 PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ", |
536 reinterpret_cast<intptr_t>(function)); | 588 reinterpret_cast<intptr_t>(function)); |
537 function->PrintName(); | 589 function->PrintName(); |
(...skipping 20 matching lines...) Expand all Loading... | |
558 d.slot_address()); | 610 d.slot_address()); |
559 } | 611 } |
560 | 612 |
561 Memory::Object_at(d.slot_address()) = *num; | 613 Memory::Object_at(d.slot_address()) = *num; |
562 } | 614 } |
563 } | 615 } |
564 | 616 |
565 | 617 |
566 #ifdef ENABLE_DEBUGGER_SUPPORT | 618 #ifdef ENABLE_DEBUGGER_SUPPORT |
567 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | 619 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
568 Address top, uint32_t size, DeoptimizedFrameInfo* info) { | 620 Address parameters_top, |
621 uint32_t parameters_size, | |
622 Address expressions_top, | |
623 uint32_t expressions_size, | |
624 DeoptimizedFrameInfo* info) { | |
569 ASSERT_EQ(DEBUGGER, bailout_type_); | 625 ASSERT_EQ(DEBUGGER, bailout_type_); |
626 Address parameters_bot = parameters_top + parameters_size; | |
Kevin Millikin (Chromium)
2012/01/24 00:08:54
_bottom reads better.
| |
627 Address expressions_bot = expressions_top + expressions_size; | |
570 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 628 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
571 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | 629 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
572 | 630 |
573 // Check of the heap number to materialize actually belong to the frame | 631 // Check of the heap number to materialize actually belong to the frame |
574 // being extracted. | 632 // being extracted. |
575 Address slot = d.slot_address(); | 633 Address slot = d.slot_address(); |
576 if (top <= slot && slot < top + size) { | 634 if (parameters_top <= slot && slot < parameters_bot) { |
577 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 635 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
578 // Calculate the index with the botton of the expression stack | 636 |
579 // at index 0, and the fixed part (including incoming arguments) | 637 int index = (info->parameters_count() - 1) - |
580 // at negative indexes. | 638 (slot - parameters_top) / kPointerSize; |
581 int index = static_cast<int>( | 639 |
582 info->expression_count_ - (slot - top) / kPointerSize - 1); | |
583 if (FLAG_trace_deopt) { | 640 if (FLAG_trace_deopt) { |
584 PrintF("Materializing a new heap number %p [%e] in slot %p" | 641 PrintF("Materializing a new heap number %p [%e] in slot %p" |
585 "for stack index %d\n", | 642 "for parameter slot #%d\n", |
586 reinterpret_cast<void*>(*num), | 643 reinterpret_cast<void*>(*num), |
587 d.value(), | 644 d.value(), |
588 d.slot_address(), | 645 d.slot_address(), |
589 index); | 646 index); |
590 } | 647 } |
591 if (index >=0) { | 648 |
592 info->SetExpression(index, *num); | 649 info->SetParameter(index, *num); |
593 } else { | 650 } else if (expressions_top <= slot && slot < expressions_bot) { |
594 // Calculate parameter index subtracting one for the receiver. | 651 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
595 int parameter_index = | 652 |
596 index + | 653 int index = info->expression_count() - 1 - |
597 static_cast<int>(size) / kPointerSize - | 654 (slot - expressions_top) / kPointerSize; |
598 info->expression_count_ - 1; | 655 |
599 info->SetParameter(parameter_index, *num); | 656 if (FLAG_trace_deopt) { |
657 PrintF("Materializing a new heap number %p [%e] in slot %p" | |
658 "for expression slot #%d\n", | |
659 reinterpret_cast<void*>(*num), | |
660 d.value(), | |
661 d.slot_address(), | |
662 index); | |
600 } | 663 } |
664 | |
665 info->SetExpression(index, *num); | |
601 } | 666 } |
602 } | 667 } |
603 } | 668 } |
604 #endif | 669 #endif |
605 | 670 |
606 | 671 |
607 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, | 672 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
608 int frame_index, | 673 int frame_index, |
609 unsigned output_offset) { | 674 unsigned output_offset) { |
610 disasm::NameConverter converter; | 675 disasm::NameConverter converter; |
611 // A GC-safe temporary placeholder that we can put in the output frame. | 676 // A GC-safe temporary placeholder that we can put in the output frame. |
612 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); | 677 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); |
613 | 678 |
614 // Ignore commands marked as duplicate and act on the first non-duplicate. | 679 // Ignore commands marked as duplicate and act on the first non-duplicate. |
615 Translation::Opcode opcode = | 680 Translation::Opcode opcode = |
616 static_cast<Translation::Opcode>(iterator->Next()); | 681 static_cast<Translation::Opcode>(iterator->Next()); |
617 while (opcode == Translation::DUPLICATE) { | 682 while (opcode == Translation::DUPLICATE) { |
618 opcode = static_cast<Translation::Opcode>(iterator->Next()); | 683 opcode = static_cast<Translation::Opcode>(iterator->Next()); |
619 iterator->Skip(Translation::NumberOfOperandsFor(opcode)); | 684 iterator->Skip(Translation::NumberOfOperandsFor(opcode)); |
620 opcode = static_cast<Translation::Opcode>(iterator->Next()); | 685 opcode = static_cast<Translation::Opcode>(iterator->Next()); |
621 } | 686 } |
622 | 687 |
623 switch (opcode) { | 688 switch (opcode) { |
624 case Translation::BEGIN: | 689 case Translation::BEGIN: |
625 case Translation::FRAME: | 690 case Translation::JS_FRAME: |
691 case Translation::ARGUMENTS_ADAPTOR_FRAME: | |
626 case Translation::DUPLICATE: | 692 case Translation::DUPLICATE: |
627 UNREACHABLE(); | 693 UNREACHABLE(); |
628 return; | 694 return; |
629 | 695 |
630 case Translation::REGISTER: { | 696 case Translation::REGISTER: { |
631 int input_reg = iterator->Next(); | 697 int input_reg = iterator->Next(); |
632 intptr_t input_value = input_->GetRegister(input_reg); | 698 intptr_t input_value = input_->GetRegister(input_reg); |
633 if (FLAG_trace_deopt) { | 699 if (FLAG_trace_deopt) { |
634 PrintF( | 700 PrintF( |
635 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", | 701 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
684 // We save the untagged value on the side and store a GC-safe | 750 // We save the untagged value on the side and store a GC-safe |
685 // temporary placeholder in the frame. | 751 // temporary placeholder in the frame. |
686 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value); | 752 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value); |
687 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); | 753 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); |
688 return; | 754 return; |
689 } | 755 } |
690 | 756 |
691 case Translation::STACK_SLOT: { | 757 case Translation::STACK_SLOT: { |
692 int input_slot_index = iterator->Next(); | 758 int input_slot_index = iterator->Next(); |
693 unsigned input_offset = | 759 unsigned input_offset = |
694 input_->GetOffsetFromSlotIndex(this, input_slot_index); | 760 input_->GetOffsetFromSlotIndex(input_slot_index); |
695 intptr_t input_value = input_->GetFrameSlot(input_offset); | 761 intptr_t input_value = input_->GetFrameSlot(input_offset); |
696 if (FLAG_trace_deopt) { | 762 if (FLAG_trace_deopt) { |
697 PrintF(" 0x%08" V8PRIxPTR ": ", | 763 PrintF(" 0x%08" V8PRIxPTR ": ", |
698 output_[frame_index]->GetTop() + output_offset); | 764 output_[frame_index]->GetTop() + output_offset); |
699 PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] ", | 765 PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] ", |
700 output_offset, | 766 output_offset, |
701 input_value, | 767 input_value, |
702 input_offset); | 768 input_offset); |
703 reinterpret_cast<Object*>(input_value)->ShortPrint(); | 769 reinterpret_cast<Object*>(input_value)->ShortPrint(); |
704 PrintF("\n"); | 770 PrintF("\n"); |
705 } | 771 } |
706 output_[frame_index]->SetFrameSlot(output_offset, input_value); | 772 output_[frame_index]->SetFrameSlot(output_offset, input_value); |
707 return; | 773 return; |
708 } | 774 } |
709 | 775 |
710 case Translation::INT32_STACK_SLOT: { | 776 case Translation::INT32_STACK_SLOT: { |
711 int input_slot_index = iterator->Next(); | 777 int input_slot_index = iterator->Next(); |
712 unsigned input_offset = | 778 unsigned input_offset = |
713 input_->GetOffsetFromSlotIndex(this, input_slot_index); | 779 input_->GetOffsetFromSlotIndex(input_slot_index); |
714 intptr_t value = input_->GetFrameSlot(input_offset); | 780 intptr_t value = input_->GetFrameSlot(input_offset); |
715 bool is_smi = Smi::IsValid(value); | 781 bool is_smi = Smi::IsValid(value); |
716 if (FLAG_trace_deopt) { | 782 if (FLAG_trace_deopt) { |
717 PrintF(" 0x%08" V8PRIxPTR ": ", | 783 PrintF(" 0x%08" V8PRIxPTR ": ", |
718 output_[frame_index]->GetTop() + output_offset); | 784 output_[frame_index]->GetTop() + output_offset); |
719 PrintF("[top + %d] <- %" V8PRIdPTR " ; [esp + %d] (%s)\n", | 785 PrintF("[top + %d] <- %" V8PRIdPTR " ; [esp + %d] (%s)\n", |
720 output_offset, | 786 output_offset, |
721 value, | 787 value, |
722 input_offset, | 788 input_offset, |
723 is_smi ? "smi" : "heap number"); | 789 is_smi ? "smi" : "heap number"); |
724 } | 790 } |
725 if (is_smi) { | 791 if (is_smi) { |
726 intptr_t tagged_value = | 792 intptr_t tagged_value = |
727 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value))); | 793 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value))); |
728 output_[frame_index]->SetFrameSlot(output_offset, tagged_value); | 794 output_[frame_index]->SetFrameSlot(output_offset, tagged_value); |
729 } else { | 795 } else { |
730 // We save the untagged value on the side and store a GC-safe | 796 // We save the untagged value on the side and store a GC-safe |
731 // temporary placeholder in the frame. | 797 // temporary placeholder in the frame. |
732 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, | 798 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, |
733 static_cast<double>(static_cast<int32_t>(value))); | 799 static_cast<double>(static_cast<int32_t>(value))); |
734 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); | 800 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); |
735 } | 801 } |
736 return; | 802 return; |
737 } | 803 } |
738 | 804 |
739 case Translation::DOUBLE_STACK_SLOT: { | 805 case Translation::DOUBLE_STACK_SLOT: { |
740 int input_slot_index = iterator->Next(); | 806 int input_slot_index = iterator->Next(); |
741 unsigned input_offset = | 807 unsigned input_offset = |
742 input_->GetOffsetFromSlotIndex(this, input_slot_index); | 808 input_->GetOffsetFromSlotIndex(input_slot_index); |
743 double value = input_->GetDoubleFrameSlot(input_offset); | 809 double value = input_->GetDoubleFrameSlot(input_offset); |
744 if (FLAG_trace_deopt) { | 810 if (FLAG_trace_deopt) { |
745 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n", | 811 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n", |
746 output_[frame_index]->GetTop() + output_offset, | 812 output_[frame_index]->GetTop() + output_offset, |
747 output_offset, | 813 output_offset, |
748 value, | 814 value, |
749 input_offset); | 815 input_offset); |
750 } | 816 } |
751 // We save the untagged value on the side and store a GC-safe | 817 // We save the untagged value on the side and store a GC-safe |
752 // temporary placeholder in the frame. | 818 // temporary placeholder in the frame. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
801 | 867 |
802 Translation::Opcode opcode = | 868 Translation::Opcode opcode = |
803 static_cast<Translation::Opcode>(iterator->Next()); | 869 static_cast<Translation::Opcode>(iterator->Next()); |
804 bool duplicate = (opcode == Translation::DUPLICATE); | 870 bool duplicate = (opcode == Translation::DUPLICATE); |
805 if (duplicate) { | 871 if (duplicate) { |
806 opcode = static_cast<Translation::Opcode>(iterator->Next()); | 872 opcode = static_cast<Translation::Opcode>(iterator->Next()); |
807 } | 873 } |
808 | 874 |
809 switch (opcode) { | 875 switch (opcode) { |
810 case Translation::BEGIN: | 876 case Translation::BEGIN: |
811 case Translation::FRAME: | 877 case Translation::JS_FRAME: |
878 case Translation::ARGUMENTS_ADAPTOR_FRAME: | |
812 case Translation::DUPLICATE: | 879 case Translation::DUPLICATE: |
813 UNREACHABLE(); // Malformed input. | 880 UNREACHABLE(); // Malformed input. |
814 return false; | 881 return false; |
815 | 882 |
816 case Translation::REGISTER: { | 883 case Translation::REGISTER: { |
817 int output_reg = iterator->Next(); | 884 int output_reg = iterator->Next(); |
818 if (FLAG_trace_osr) { | 885 if (FLAG_trace_osr) { |
819 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", | 886 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", |
820 converter.NameOfCPURegister(output_reg), | 887 converter.NameOfCPURegister(output_reg), |
821 input_value, | 888 input_value, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
864 double_value, | 931 double_value, |
865 *input_offset); | 932 *input_offset); |
866 } | 933 } |
867 output->SetDoubleRegister(output_reg, double_value); | 934 output->SetDoubleRegister(output_reg, double_value); |
868 break; | 935 break; |
869 } | 936 } |
870 | 937 |
871 case Translation::STACK_SLOT: { | 938 case Translation::STACK_SLOT: { |
872 int output_index = iterator->Next(); | 939 int output_index = iterator->Next(); |
873 unsigned output_offset = | 940 unsigned output_offset = |
874 output->GetOffsetFromSlotIndex(this, output_index); | 941 output->GetOffsetFromSlotIndex(output_index); |
875 if (FLAG_trace_osr) { | 942 if (FLAG_trace_osr) { |
876 PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ", | 943 PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ", |
877 output_offset, | 944 output_offset, |
878 input_value, | 945 input_value, |
879 *input_offset); | 946 *input_offset); |
880 reinterpret_cast<Object*>(input_value)->ShortPrint(); | 947 reinterpret_cast<Object*>(input_value)->ShortPrint(); |
881 PrintF("\n"); | 948 PrintF("\n"); |
882 } | 949 } |
883 output->SetFrameSlot(output_offset, input_value); | 950 output->SetFrameSlot(output_offset, input_value); |
884 break; | 951 break; |
885 } | 952 } |
886 | 953 |
887 case Translation::INT32_STACK_SLOT: { | 954 case Translation::INT32_STACK_SLOT: { |
888 // Abort OSR if we don't have a number. | 955 // Abort OSR if we don't have a number. |
889 if (!input_object->IsNumber()) return false; | 956 if (!input_object->IsNumber()) return false; |
890 | 957 |
891 int output_index = iterator->Next(); | 958 int output_index = iterator->Next(); |
892 unsigned output_offset = | 959 unsigned output_offset = |
893 output->GetOffsetFromSlotIndex(this, output_index); | 960 output->GetOffsetFromSlotIndex(output_index); |
894 int int32_value = input_object->IsSmi() | 961 int int32_value = input_object->IsSmi() |
895 ? Smi::cast(input_object)->value() | 962 ? Smi::cast(input_object)->value() |
896 : DoubleToInt32(input_object->Number()); | 963 : DoubleToInt32(input_object->Number()); |
897 // Abort the translation if the conversion lost information. | 964 // Abort the translation if the conversion lost information. |
898 if (!input_object->IsSmi() && | 965 if (!input_object->IsSmi() && |
899 FastI2D(int32_value) != input_object->Number()) { | 966 FastI2D(int32_value) != input_object->Number()) { |
900 if (FLAG_trace_osr) { | 967 if (FLAG_trace_osr) { |
901 PrintF("**** %g could not be converted to int32 ****\n", | 968 PrintF("**** %g could not be converted to int32 ****\n", |
902 input_object->Number()); | 969 input_object->Number()); |
903 } | 970 } |
(...skipping 11 matching lines...) Expand all Loading... | |
915 | 982 |
916 case Translation::DOUBLE_STACK_SLOT: { | 983 case Translation::DOUBLE_STACK_SLOT: { |
917 static const int kLowerOffset = 0 * kPointerSize; | 984 static const int kLowerOffset = 0 * kPointerSize; |
918 static const int kUpperOffset = 1 * kPointerSize; | 985 static const int kUpperOffset = 1 * kPointerSize; |
919 | 986 |
920 // Abort OSR if we don't have a number. | 987 // Abort OSR if we don't have a number. |
921 if (!input_object->IsNumber()) return false; | 988 if (!input_object->IsNumber()) return false; |
922 | 989 |
923 int output_index = iterator->Next(); | 990 int output_index = iterator->Next(); |
924 unsigned output_offset = | 991 unsigned output_offset = |
925 output->GetOffsetFromSlotIndex(this, output_index); | 992 output->GetOffsetFromSlotIndex(output_index); |
926 double double_value = input_object->Number(); | 993 double double_value = input_object->Number(); |
927 uint64_t int_value = BitCast<uint64_t, double>(double_value); | 994 uint64_t int_value = BitCast<uint64_t, double>(double_value); |
928 int32_t lower = static_cast<int32_t>(int_value); | 995 int32_t lower = static_cast<int32_t>(int_value); |
929 int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt); | 996 int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt); |
930 if (FLAG_trace_osr) { | 997 if (FLAG_trace_osr) { |
931 PrintF(" [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n", | 998 PrintF(" [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n", |
932 output_offset + kUpperOffset, | 999 output_offset + kUpperOffset, |
933 upper, | 1000 upper, |
934 double_value, | 1001 double_value, |
935 *input_offset); | 1002 *input_offset); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1026 ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); | 1093 ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); |
1027 } | 1094 } |
1028 #endif | 1095 #endif |
1029 return result; | 1096 return result; |
1030 } | 1097 } |
1031 | 1098 |
1032 | 1099 |
1033 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { | 1100 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { |
1034 // The fixed part of the frame consists of the return address, frame | 1101 // The fixed part of the frame consists of the return address, frame |
1035 // pointer, function, context, and all the incoming arguments. | 1102 // pointer, function, context, and all the incoming arguments. |
1036 static const unsigned kFixedSlotSize = 4 * kPointerSize; | 1103 return ComputeIncomingArgumentSize(function) + |
1037 return ComputeIncomingArgumentSize(function) + kFixedSlotSize; | 1104 StandardFrameConstants::kFixedFrameSize * kPointerSize; |
1038 } | 1105 } |
1039 | 1106 |
1040 | 1107 |
1041 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { | 1108 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { |
1042 // The incoming arguments is the values for formal parameters and | 1109 // The incoming arguments is the values for formal parameters and |
1043 // the receiver. Every slot contains a pointer. | 1110 // the receiver. Every slot contains a pointer. |
1044 unsigned arguments = function->shared()->formal_parameter_count() + 1; | 1111 unsigned arguments = function->shared()->formal_parameter_count() + 1; |
1045 return arguments * kPointerSize; | 1112 return arguments * kPointerSize; |
1046 } | 1113 } |
1047 | 1114 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1147 SetRegister(r, kZapUint32); | 1214 SetRegister(r, kZapUint32); |
1148 } | 1215 } |
1149 | 1216 |
1150 // Zap all the slots. | 1217 // Zap all the slots. |
1151 for (unsigned o = 0; o < frame_size; o += kPointerSize) { | 1218 for (unsigned o = 0; o < frame_size; o += kPointerSize) { |
1152 SetFrameSlot(o, kZapUint32); | 1219 SetFrameSlot(o, kZapUint32); |
1153 } | 1220 } |
1154 } | 1221 } |
1155 | 1222 |
1156 | 1223 |
1157 unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, | 1224 int FrameDescription::ComputeFixedSize() { |
1158 int slot_index) { | 1225 return StandardFrameConstants::kFixedFrameSize * kPointerSize + |
1226 (ComputeParametersCount() + 1) * kPointerSize; | |
1227 } | |
1228 | |
1229 | |
1230 unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) { | |
1159 if (slot_index >= 0) { | 1231 if (slot_index >= 0) { |
1160 // Local or spill slots. Skip the fixed part of the frame | 1232 // Local or spill slots. Skip the fixed part of the frame |
1161 // including all arguments. | 1233 // including all arguments. |
1162 unsigned base = | 1234 unsigned base = GetFrameSize() - ComputeFixedSize(); |
1163 GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); | |
1164 return base - ((slot_index + 1) * kPointerSize); | 1235 return base - ((slot_index + 1) * kPointerSize); |
1165 } else { | 1236 } else { |
1166 // Incoming parameter. | 1237 // Incoming parameter. |
1167 unsigned base = GetFrameSize() - | 1238 int arg_size = (ComputeParametersCount() + 1) * kPointerSize; |
1168 deoptimizer->ComputeIncomingArgumentSize(GetFunction()); | 1239 unsigned base = GetFrameSize() - arg_size; |
1169 return base - ((slot_index + 1) * kPointerSize); | 1240 return base - ((slot_index + 1) * kPointerSize); |
1170 } | 1241 } |
1171 } | 1242 } |
1172 | 1243 |
1173 | 1244 |
1174 int FrameDescription::ComputeParametersCount() { | 1245 int FrameDescription::ComputeParametersCount() { |
1175 return function_->shared()->formal_parameter_count(); | 1246 switch (type_) { |
1247 case StackFrame::JAVA_SCRIPT: | |
1248 return function_->shared()->formal_parameter_count(); | |
1249 case StackFrame::ARGUMENTS_ADAPTOR: { | |
1250 // Last slot contains number of incomming arguments as a smi. | |
1251 // Can't use GetExpression(0) because it would cause infinite recursion. | |
1252 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); | |
1253 } | |
1254 default: | |
1255 UNREACHABLE(); | |
1256 return 0; | |
1257 } | |
1176 } | 1258 } |
1177 | 1259 |
1178 | 1260 |
1179 Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) { | 1261 Object* FrameDescription::GetParameter(int index) { |
1180 ASSERT_EQ(Code::FUNCTION, kind_); | |
1181 ASSERT(index >= 0); | 1262 ASSERT(index >= 0); |
1182 ASSERT(index < ComputeParametersCount()); | 1263 ASSERT(index < ComputeParametersCount()); |
1183 // The slot indexes for incoming arguments are negative. | 1264 // The slot indexes for incoming arguments are negative. |
1184 unsigned offset = GetOffsetFromSlotIndex(deoptimizer, | 1265 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); |
1185 index - ComputeParametersCount()); | |
1186 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 1266 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
1187 } | 1267 } |
1188 | 1268 |
1189 | 1269 |
1190 unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { | 1270 unsigned FrameDescription::GetExpressionCount() { |
1191 ASSERT_EQ(Code::FUNCTION, kind_); | 1271 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); |
1192 unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); | 1272 unsigned size = GetFrameSize() - ComputeFixedSize(); |
1193 return size / kPointerSize; | 1273 return size / kPointerSize; |
1194 } | 1274 } |
1195 | 1275 |
1196 | 1276 |
1197 Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { | 1277 Object* FrameDescription::GetExpression(int index) { |
1198 ASSERT_EQ(Code::FUNCTION, kind_); | 1278 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); |
1199 unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); | 1279 unsigned offset = GetOffsetFromSlotIndex(index); |
1200 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 1280 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
1201 } | 1281 } |
1202 | 1282 |
1203 | 1283 |
1204 void TranslationBuffer::Add(int32_t value) { | 1284 void TranslationBuffer::Add(int32_t value) { |
1205 // Encode the sign bit in the least significant bit. | 1285 // Encode the sign bit in the least significant bit. |
1206 bool is_negative = (value < 0); | 1286 bool is_negative = (value < 0); |
1207 uint32_t bits = ((is_negative ? -value : value) << 1) | | 1287 uint32_t bits = ((is_negative ? -value : value) << 1) | |
1208 static_cast<int32_t>(is_negative); | 1288 static_cast<int32_t>(is_negative); |
1209 // Encode the individual bytes using the least significant bit of | 1289 // Encode the individual bytes using the least significant bit of |
(...skipping 25 matching lines...) Expand all Loading... | |
1235 | 1315 |
1236 Handle<ByteArray> TranslationBuffer::CreateByteArray() { | 1316 Handle<ByteArray> TranslationBuffer::CreateByteArray() { |
1237 int length = contents_.length(); | 1317 int length = contents_.length(); |
1238 Handle<ByteArray> result = | 1318 Handle<ByteArray> result = |
1239 Isolate::Current()->factory()->NewByteArray(length, TENURED); | 1319 Isolate::Current()->factory()->NewByteArray(length, TENURED); |
1240 memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length); | 1320 memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length); |
1241 return result; | 1321 return result; |
1242 } | 1322 } |
1243 | 1323 |
1244 | 1324 |
1245 void Translation::BeginFrame(int node_id, int literal_id, unsigned height) { | 1325 void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) { |
1246 buffer_->Add(FRAME); | 1326 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME); |
1327 buffer_->Add(literal_id); | |
1328 buffer_->Add(height); | |
1329 } | |
1330 | |
1331 | |
1332 void Translation::BeginJSFrame(int node_id, int literal_id, unsigned height) { | |
1333 buffer_->Add(JS_FRAME); | |
1247 buffer_->Add(node_id); | 1334 buffer_->Add(node_id); |
1248 buffer_->Add(literal_id); | 1335 buffer_->Add(literal_id); |
1249 buffer_->Add(height); | 1336 buffer_->Add(height); |
1250 } | 1337 } |
1251 | 1338 |
1252 | 1339 |
1253 void Translation::StoreRegister(Register reg) { | 1340 void Translation::StoreRegister(Register reg) { |
1254 buffer_->Add(REGISTER); | 1341 buffer_->Add(REGISTER); |
1255 buffer_->Add(reg.code()); | 1342 buffer_->Add(reg.code()); |
1256 } | 1343 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1300 void Translation::MarkDuplicate() { | 1387 void Translation::MarkDuplicate() { |
1301 buffer_->Add(DUPLICATE); | 1388 buffer_->Add(DUPLICATE); |
1302 } | 1389 } |
1303 | 1390 |
1304 | 1391 |
1305 int Translation::NumberOfOperandsFor(Opcode opcode) { | 1392 int Translation::NumberOfOperandsFor(Opcode opcode) { |
1306 switch (opcode) { | 1393 switch (opcode) { |
1307 case ARGUMENTS_OBJECT: | 1394 case ARGUMENTS_OBJECT: |
1308 case DUPLICATE: | 1395 case DUPLICATE: |
1309 return 0; | 1396 return 0; |
1310 case BEGIN: | |
1311 case REGISTER: | 1397 case REGISTER: |
1312 case INT32_REGISTER: | 1398 case INT32_REGISTER: |
1313 case DOUBLE_REGISTER: | 1399 case DOUBLE_REGISTER: |
1314 case STACK_SLOT: | 1400 case STACK_SLOT: |
1315 case INT32_STACK_SLOT: | 1401 case INT32_STACK_SLOT: |
1316 case DOUBLE_STACK_SLOT: | 1402 case DOUBLE_STACK_SLOT: |
1317 case LITERAL: | 1403 case LITERAL: |
1318 return 1; | 1404 return 1; |
1319 case FRAME: | 1405 case BEGIN: |
1406 case ARGUMENTS_ADAPTOR_FRAME: | |
1407 return 2; | |
1408 case JS_FRAME: | |
1320 return 3; | 1409 return 3; |
1321 } | 1410 } |
1322 UNREACHABLE(); | 1411 UNREACHABLE(); |
1323 return -1; | 1412 return -1; |
1324 } | 1413 } |
1325 | 1414 |
1326 | 1415 |
1327 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) | 1416 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) |
1328 | 1417 |
1329 const char* Translation::StringFor(Opcode opcode) { | 1418 const char* Translation::StringFor(Opcode opcode) { |
1330 switch (opcode) { | 1419 switch (opcode) { |
1331 case BEGIN: | 1420 case BEGIN: |
1332 return "BEGIN"; | 1421 return "BEGIN"; |
1333 case FRAME: | 1422 case JS_FRAME: |
1334 return "FRAME"; | 1423 return "JS_FRAME"; |
1424 case ARGUMENTS_ADAPTOR_FRAME: | |
1425 return "ARGUMENTS_ADAPTOR_FRAME"; | |
1335 case REGISTER: | 1426 case REGISTER: |
1336 return "REGISTER"; | 1427 return "REGISTER"; |
1337 case INT32_REGISTER: | 1428 case INT32_REGISTER: |
1338 return "INT32_REGISTER"; | 1429 return "INT32_REGISTER"; |
1339 case DOUBLE_REGISTER: | 1430 case DOUBLE_REGISTER: |
1340 return "DOUBLE_REGISTER"; | 1431 return "DOUBLE_REGISTER"; |
1341 case STACK_SLOT: | 1432 case STACK_SLOT: |
1342 return "STACK_SLOT"; | 1433 return "STACK_SLOT"; |
1343 case INT32_STACK_SLOT: | 1434 case INT32_STACK_SLOT: |
1344 return "INT32_STACK_SLOT"; | 1435 return "INT32_STACK_SLOT"; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1378 // deoptimization infrastracture is not GC safe. | 1469 // deoptimization infrastracture is not GC safe. |
1379 // Thus we build a temporary structure in malloced space. | 1470 // Thus we build a temporary structure in malloced space. |
1380 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, | 1471 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, |
1381 DeoptimizationInputData* data, | 1472 DeoptimizationInputData* data, |
1382 JavaScriptFrame* frame) { | 1473 JavaScriptFrame* frame) { |
1383 Translation::Opcode opcode = | 1474 Translation::Opcode opcode = |
1384 static_cast<Translation::Opcode>(iterator->Next()); | 1475 static_cast<Translation::Opcode>(iterator->Next()); |
1385 | 1476 |
1386 switch (opcode) { | 1477 switch (opcode) { |
1387 case Translation::BEGIN: | 1478 case Translation::BEGIN: |
1388 case Translation::FRAME: | 1479 case Translation::JS_FRAME: |
1480 case Translation::ARGUMENTS_ADAPTOR_FRAME: | |
1389 // Peeled off before getting here. | 1481 // Peeled off before getting here. |
1390 break; | 1482 break; |
1391 | 1483 |
1392 case Translation::ARGUMENTS_OBJECT: | 1484 case Translation::ARGUMENTS_OBJECT: |
1393 // This can be only emitted for local slots not for argument slots. | 1485 // This can be only emitted for local slots not for argument slots. |
1394 break; | 1486 break; |
1395 | 1487 |
1396 case Translation::REGISTER: | 1488 case Translation::REGISTER: |
1397 case Translation::INT32_REGISTER: | 1489 case Translation::INT32_REGISTER: |
1398 case Translation::DOUBLE_REGISTER: | 1490 case Translation::DOUBLE_REGISTER: |
(...skipping 25 matching lines...) Expand all Loading... | |
1424 int literal_index = iterator->Next(); | 1516 int literal_index = iterator->Next(); |
1425 return SlotRef(data->LiteralArray()->get(literal_index)); | 1517 return SlotRef(data->LiteralArray()->get(literal_index)); |
1426 } | 1518 } |
1427 } | 1519 } |
1428 | 1520 |
1429 UNREACHABLE(); | 1521 UNREACHABLE(); |
1430 return SlotRef(); | 1522 return SlotRef(); |
1431 } | 1523 } |
1432 | 1524 |
1433 | 1525 |
1434 void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, | 1526 void SlotRef::ComputeSlotsForArguments(Vector<SlotRef>* args_slots, |
1435 int inlined_frame_index, | 1527 TranslationIterator* it, |
1436 Vector<SlotRef>* args_slots) { | 1528 DeoptimizationInputData* data, |
1529 JavaScriptFrame* frame) { | |
1530 // Process the translation commands for the arguments. | |
1531 | |
1532 // Skip the translation command for the receiver. | |
1533 it->Skip(Translation::NumberOfOperandsFor( | |
1534 static_cast<Translation::Opcode>(it->Next()))); | |
1535 | |
1536 // Compute slots for arguments. | |
1537 for (int i = 0; i < args_slots->length(); ++i) { | |
1538 (*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame); | |
1539 } | |
1540 } | |
1541 | |
1542 | |
1543 Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments( | |
1544 JavaScriptFrame* frame, | |
1545 int inlined_jsframe_index, | |
1546 int formal_parameter_count) { | |
1437 AssertNoAllocation no_gc; | 1547 AssertNoAllocation no_gc; |
1438 int deopt_index = AstNode::kNoNumber; | 1548 int deopt_index = AstNode::kNoNumber; |
1439 DeoptimizationInputData* data = | 1549 DeoptimizationInputData* data = |
1440 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | 1550 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); |
1441 TranslationIterator it(data->TranslationByteArray(), | 1551 TranslationIterator it(data->TranslationByteArray(), |
1442 data->TranslationIndex(deopt_index)->value()); | 1552 data->TranslationIndex(deopt_index)->value()); |
1443 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 1553 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
1444 ASSERT(opcode == Translation::BEGIN); | 1554 ASSERT(opcode == Translation::BEGIN); |
1445 int frame_count = it.Next(); | 1555 it.Next(); // Drop frame count. |
1446 USE(frame_count); | 1556 int jsframe_count = it.Next(); |
1447 ASSERT(frame_count > inlined_frame_index); | 1557 USE(jsframe_count); |
1448 int frames_to_skip = inlined_frame_index; | 1558 ASSERT(jsframe_count > inlined_jsframe_index); |
1559 int jsframes_to_skip = inlined_jsframe_index; | |
1449 while (true) { | 1560 while (true) { |
1450 opcode = static_cast<Translation::Opcode>(it.Next()); | 1561 opcode = static_cast<Translation::Opcode>(it.Next()); |
1562 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { | |
1563 if (jsframes_to_skip == 0) { | |
1564 ASSERT(Translation::NumberOfOperandsFor(opcode) == 2); | |
1565 | |
1566 it.Skip(1); // literal id | |
1567 int height = it.Next(); | |
1568 | |
1569 // We reached the arguments adaptor frame corresponding to the | |
1570 // inlined function in question. Number of arguments is height - 1. | |
1571 Vector<SlotRef> args_slots = | |
1572 Vector<SlotRef>::New(height - 1); // Minus receiver. | |
1573 ComputeSlotsForArguments(&args_slots, &it, data, frame); | |
1574 return args_slots; | |
1575 } | |
1576 } else if (opcode == Translation::JS_FRAME) { | |
1577 if (jsframes_to_skip == 0) { | |
1578 // Skip over operands to advance to the next opcode. | |
1579 it.Skip(Translation::NumberOfOperandsFor(opcode)); | |
1580 | |
1581 // We reached the frame corresponding to the inlined function | |
1582 // in question. Process the translation commands for the | |
1583 // arguments. Number of arguments is equal to the number of | |
1584 // format parameter count. | |
1585 Vector<SlotRef> args_slots = | |
1586 Vector<SlotRef>::New(formal_parameter_count); | |
1587 ComputeSlotsForArguments(&args_slots, &it, data, frame); | |
1588 return args_slots; | |
1589 } | |
1590 jsframes_to_skip--; | |
1591 } | |
1592 | |
1451 // Skip over operands to advance to the next opcode. | 1593 // Skip over operands to advance to the next opcode. |
1452 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 1594 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
1453 if (opcode == Translation::FRAME) { | |
1454 if (frames_to_skip == 0) { | |
1455 // We reached the frame corresponding to the inlined function | |
1456 // in question. Process the translation commands for the | |
1457 // arguments. | |
1458 // | |
1459 // Skip the translation command for the receiver. | |
1460 it.Skip(Translation::NumberOfOperandsFor( | |
1461 static_cast<Translation::Opcode>(it.Next()))); | |
1462 // Compute slots for arguments. | |
1463 for (int i = 0; i < args_slots->length(); ++i) { | |
1464 (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); | |
1465 } | |
1466 return; | |
1467 } | |
1468 frames_to_skip--; | |
1469 } | |
1470 } | 1595 } |
1471 | 1596 |
1472 UNREACHABLE(); | 1597 UNREACHABLE(); |
1598 return Vector<SlotRef>(); | |
1473 } | 1599 } |
1474 | 1600 |
1475 #ifdef ENABLE_DEBUGGER_SUPPORT | 1601 #ifdef ENABLE_DEBUGGER_SUPPORT |
1476 | 1602 |
1477 DeoptimizedFrameInfo::DeoptimizedFrameInfo( | 1603 DeoptimizedFrameInfo::DeoptimizedFrameInfo( |
1478 Deoptimizer* deoptimizer, int frame_index) { | 1604 Deoptimizer* deoptimizer, int frame_index, bool has_arguments_adaptor) { |
1479 FrameDescription* output_frame = deoptimizer->output_[frame_index]; | 1605 FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
1480 SetFunction(output_frame->GetFunction()); | 1606 SetFunction(output_frame->GetFunction()); |
1481 expression_count_ = output_frame->GetExpressionCount(deoptimizer); | 1607 expression_count_ = output_frame->GetExpressionCount(); |
1608 expression_stack_ = new Object*[expression_count_]; | |
1609 for (int i = 0; i < expression_count_; i++) { | |
1610 SetExpression(i, output_frame->GetExpression(i)); | |
1611 } | |
1612 | |
1613 if (has_arguments_adaptor) { | |
1614 output_frame = deoptimizer->output_[frame_index - 1]; | |
1615 ASSERT(output_frame->GetType() == StackFrame::ARGUMENTS_ADAPTOR); | |
1616 } | |
1617 | |
1482 parameters_count_ = output_frame->ComputeParametersCount(); | 1618 parameters_count_ = output_frame->ComputeParametersCount(); |
1483 parameters_ = new Object*[parameters_count_]; | 1619 parameters_ = new Object*[parameters_count_]; |
1484 for (int i = 0; i < parameters_count_; i++) { | 1620 for (int i = 0; i < parameters_count_; i++) { |
1485 SetParameter(i, output_frame->GetParameter(deoptimizer, i)); | 1621 SetParameter(i, output_frame->GetParameter(i)); |
1486 } | |
1487 expression_stack_ = new Object*[expression_count_]; | |
1488 for (int i = 0; i < expression_count_; i++) { | |
1489 SetExpression(i, output_frame->GetExpression(deoptimizer, i)); | |
1490 } | 1622 } |
1491 } | 1623 } |
1492 | 1624 |
1493 | 1625 |
1494 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { | 1626 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { |
1495 delete[] expression_stack_; | 1627 delete[] expression_stack_; |
1496 delete[] parameters_; | 1628 delete[] parameters_; |
1497 } | 1629 } |
1498 | 1630 |
1499 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 1631 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
1500 v->VisitPointer(BitCast<Object**>(&function_)); | 1632 v->VisitPointer(BitCast<Object**>(&function_)); |
1501 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 1633 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
1502 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 1634 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
1503 } | 1635 } |
1504 | 1636 |
1505 #endif // ENABLE_DEBUGGER_SUPPORT | 1637 #endif // ENABLE_DEBUGGER_SUPPORT |
1506 | 1638 |
1507 } } // namespace v8::internal | 1639 } } // namespace v8::internal |
OLD | NEW |