| 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 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; | 344 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; |
| 345 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 345 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); |
| 346 unsigned outgoing_size = outgoing_height * kPointerSize; | 346 unsigned outgoing_size = outgoing_height * kPointerSize; |
| 347 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; | 347 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; |
| 348 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. | 348 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. |
| 349 | 349 |
| 350 if (FLAG_trace_osr) { | 350 if (FLAG_trace_osr) { |
| 351 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", | 351 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", |
| 352 reinterpret_cast<intptr_t>(function_)); | 352 reinterpret_cast<intptr_t>(function_)); |
| 353 function_->PrintName(); | 353 function_->PrintName(); |
| 354 PrintF(" => node=%u, frame=%d->%d]\n", | 354 PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", |
| 355 ast_id, | 355 ast_id, |
| 356 input_frame_size, | 356 input_frame_size, |
| 357 output_frame_size); | 357 output_frame_size, |
| 358 input_->GetRegister(ebp.code()), |
| 359 input_->GetRegister(esp.code())); |
| 358 } | 360 } |
| 359 | 361 |
| 360 // There's only one output frame in the OSR case. | 362 // There's only one output frame in the OSR case. |
| 361 output_count_ = 1; | 363 output_count_ = 1; |
| 362 output_ = new FrameDescription*[1]; | 364 output_ = new FrameDescription*[1]; |
| 363 output_[0] = new(output_frame_size) FrameDescription( | 365 output_[0] = new(output_frame_size) FrameDescription( |
| 364 output_frame_size, function_); | 366 output_frame_size, function_); |
| 365 output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT); | 367 output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT); |
| 366 | 368 |
| 367 // Clear the incoming parameters in the optimized frame to avoid | 369 // Clear the incoming parameters in the optimized frame to avoid |
| (...skipping 29 matching lines...) Expand all Loading... |
| 397 case StandardFrameConstants::kCallerFPOffset: | 399 case StandardFrameConstants::kCallerFPOffset: |
| 398 name = "fp"; | 400 name = "fp"; |
| 399 break; | 401 break; |
| 400 case StandardFrameConstants::kContextOffset: | 402 case StandardFrameConstants::kContextOffset: |
| 401 name = "context"; | 403 name = "context"; |
| 402 break; | 404 break; |
| 403 case StandardFrameConstants::kMarkerOffset: | 405 case StandardFrameConstants::kMarkerOffset: |
| 404 name = "function"; | 406 name = "function"; |
| 405 break; | 407 break; |
| 406 } | 408 } |
| 407 PrintF(" [esp + %d] <- 0x%08x ; [esp + %d] (fixed part - %s)\n", | 409 PrintF(" [sp + %d] <- 0x%08x ; [sp + %d] (fixed part - %s)\n", |
| 408 output_offset, | 410 output_offset, |
| 409 input_value, | 411 input_value, |
| 410 input_offset, | 412 input_offset, |
| 411 name); | 413 name); |
| 412 } | 414 } |
| 413 output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); | 415 output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); |
| 414 input_offset -= kPointerSize; | 416 input_offset -= kPointerSize; |
| 415 output_offset -= kPointerSize; | 417 output_offset -= kPointerSize; |
| 416 } | 418 } |
| 417 | 419 |
| 420 // All OSR stack frames are dynamically aligned to an 8-byte boundary. |
| 421 int frame_pointer = input_->GetRegister(ebp.code()); |
| 422 if ((frame_pointer & kPointerSize) != 0) { |
| 423 frame_pointer -= kPointerSize; |
| 424 has_alignment_padding_ = 1; |
| 425 } |
| 426 |
| 427 int32_t alignment_state = (has_alignment_padding_ == 1) ? |
| 428 kAlignmentPaddingPushed : |
| 429 kNoAlignmentPadding; |
| 430 if (FLAG_trace_osr) { |
| 431 PrintF(" [sp + %d] <- 0x%08x ; (alignment state)\n", |
| 432 output_offset, |
| 433 alignment_state); |
| 434 } |
| 435 output_[0]->SetFrameSlot(output_offset, alignment_state); |
| 436 output_offset -= kPointerSize; |
| 437 |
| 418 // Translate the rest of the frame. | 438 // Translate the rest of the frame. |
| 419 while (ok && input_offset >= 0) { | 439 while (ok && input_offset >= 0) { |
| 420 ok = DoOsrTranslateCommand(&iterator, &input_offset); | 440 ok = DoOsrTranslateCommand(&iterator, &input_offset); |
| 421 } | 441 } |
| 422 | 442 |
| 423 // If translation of any command failed, continue using the input frame. | 443 // If translation of any command failed, continue using the input frame. |
| 424 if (!ok) { | 444 if (!ok) { |
| 425 delete output_[0]; | 445 delete output_[0]; |
| 426 output_[0] = input_; | 446 output_[0] = input_; |
| 427 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); | 447 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); |
| 428 } else { | 448 } else { |
| 429 // Set up the frame pointer and the context pointer. | 449 // Set up the frame pointer and the context pointer. |
| 430 output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code())); | 450 output_[0]->SetRegister(ebp.code(), frame_pointer); |
| 431 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); | 451 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
| 432 | 452 |
| 433 unsigned pc_offset = data->OsrPcOffset()->value(); | 453 unsigned pc_offset = data->OsrPcOffset()->value(); |
| 434 uint32_t pc = reinterpret_cast<uint32_t>( | 454 uint32_t pc = reinterpret_cast<uint32_t>( |
| 435 optimized_code_->entry() + pc_offset); | 455 optimized_code_->entry() + pc_offset); |
| 436 output_[0]->SetPc(pc); | 456 output_[0]->SetPc(pc); |
| 437 } | 457 } |
| 438 Code* continuation = | 458 Code* continuation = |
| 439 function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); | 459 function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); |
| 440 output_[0]->SetContinuation( | 460 output_[0]->SetContinuation( |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 FrameDescription* output_frame = | 701 FrameDescription* output_frame = |
| 682 new(output_frame_size) FrameDescription(output_frame_size, function); | 702 new(output_frame_size) FrameDescription(output_frame_size, function); |
| 683 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); | 703 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
| 684 | 704 |
| 685 bool is_bottommost = (0 == frame_index); | 705 bool is_bottommost = (0 == frame_index); |
| 686 bool is_topmost = (output_count_ - 1 == frame_index); | 706 bool is_topmost = (output_count_ - 1 == frame_index); |
| 687 ASSERT(frame_index >= 0 && frame_index < output_count_); | 707 ASSERT(frame_index >= 0 && frame_index < output_count_); |
| 688 ASSERT(output_[frame_index] == NULL); | 708 ASSERT(output_[frame_index] == NULL); |
| 689 output_[frame_index] = output_frame; | 709 output_[frame_index] = output_frame; |
| 690 | 710 |
| 711 // Compute the incoming parameter translation. |
| 712 int parameter_count = function->shared()->formal_parameter_count() + 1; |
| 713 unsigned output_offset = output_frame_size; |
| 714 unsigned input_offset = input_frame_size; |
| 715 |
| 716 unsigned alignment_state_offset = |
| 717 input_offset - parameter_count * kPointerSize - |
| 718 StandardFrameConstants::kFixedFrameSize - |
| 719 kPointerSize; |
| 720 ASSERT(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == |
| 721 JavaScriptFrameConstants::kLocal0Offset); |
| 722 |
| 691 // The top address for the bottommost output frame can be computed from | 723 // The top address for the bottommost output frame can be computed from |
| 692 // the input frame pointer and the output frame's height. For all | 724 // the input frame pointer and the output frame's height. For all |
| 693 // subsequent output frames, it can be computed from the previous one's | 725 // subsequent output frames, it can be computed from the previous one's |
| 694 // top address and the current frame's size. | 726 // top address and the current frame's size. |
| 695 uint32_t top_address; | 727 uint32_t top_address; |
| 696 if (is_bottommost) { | 728 if (is_bottommost) { |
| 729 int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); |
| 730 has_alignment_padding_ = |
| 731 (alignment_state == kAlignmentPaddingPushed) ? 1 : 0; |
| 697 // 2 = context and function in the frame. | 732 // 2 = context and function in the frame. |
| 698 top_address = | 733 // If the optimized frame had alignment padding, adjust the frame pointer |
| 699 input_->GetRegister(ebp.code()) - (2 * kPointerSize) - height_in_bytes; | 734 // to point to the new position of the old frame pointer after padding |
| 735 // is removed. Subtract 2 * kPointerSize for the context and function slots. |
| 736 top_address = input_->GetRegister(ebp.code()) - (2 * kPointerSize) - |
| 737 height_in_bytes + has_alignment_padding_ * kPointerSize; |
| 700 } else { | 738 } else { |
| 701 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 739 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
| 702 } | 740 } |
| 703 output_frame->SetTop(top_address); | 741 output_frame->SetTop(top_address); |
| 704 | 742 |
| 705 // Compute the incoming parameter translation. | |
| 706 int parameter_count = function->shared()->formal_parameter_count() + 1; | |
| 707 unsigned output_offset = output_frame_size; | |
| 708 unsigned input_offset = input_frame_size; | |
| 709 for (int i = 0; i < parameter_count; ++i) { | 743 for (int i = 0; i < parameter_count; ++i) { |
| 710 output_offset -= kPointerSize; | 744 output_offset -= kPointerSize; |
| 711 DoTranslateCommand(iterator, frame_index, output_offset); | 745 DoTranslateCommand(iterator, frame_index, output_offset); |
| 712 } | 746 } |
| 713 input_offset -= (parameter_count * kPointerSize); | 747 input_offset -= (parameter_count * kPointerSize); |
| 714 | 748 |
| 715 // There are no translation commands for the caller's pc and fp, the | 749 // There are no translation commands for the caller's pc and fp, the |
| 716 // context, and the function. Synthesize their values and set them up | 750 // context, and the function. Synthesize their values and set them up |
| 717 // explicitly. | 751 // explicitly. |
| 718 // | 752 // |
| (...skipping 21 matching lines...) Expand all Loading... |
| 740 // pointer. | 774 // pointer. |
| 741 output_offset -= kPointerSize; | 775 output_offset -= kPointerSize; |
| 742 input_offset -= kPointerSize; | 776 input_offset -= kPointerSize; |
| 743 if (is_bottommost) { | 777 if (is_bottommost) { |
| 744 value = input_->GetFrameSlot(input_offset); | 778 value = input_->GetFrameSlot(input_offset); |
| 745 } else { | 779 } else { |
| 746 value = output_[frame_index - 1]->GetFp(); | 780 value = output_[frame_index - 1]->GetFp(); |
| 747 } | 781 } |
| 748 output_frame->SetFrameSlot(output_offset, value); | 782 output_frame->SetFrameSlot(output_offset, value); |
| 749 intptr_t fp_value = top_address + output_offset; | 783 intptr_t fp_value = top_address + output_offset; |
| 750 ASSERT(!is_bottommost || input_->GetRegister(ebp.code()) == fp_value); | 784 ASSERT(!is_bottommost || |
| 785 (input_->GetRegister(ebp.code()) + has_alignment_padding_ * kPointerSize) == |
| 786 fp_value); |
| 751 output_frame->SetFp(fp_value); | 787 output_frame->SetFp(fp_value); |
| 752 if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value); | 788 if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value); |
| 753 if (FLAG_trace_deopt) { | 789 if (FLAG_trace_deopt) { |
| 754 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", | 790 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", |
| 755 fp_value, output_offset, value); | 791 fp_value, output_offset, value); |
| 756 } | 792 } |
| 793 ASSERT(!is_bottommost || !has_alignment_padding_ || |
| 794 (fp_value & kPointerSize) != 0); |
| 757 | 795 |
| 758 // For the bottommost output frame the context can be gotten from the input | 796 // For the bottommost output frame the context can be gotten from the input |
| 759 // frame. For all subsequent output frames it can be gotten from the function | 797 // frame. For all subsequent output frames it can be gotten from the function |
| 760 // so long as we don't inline functions that need local contexts. | 798 // so long as we don't inline functions that need local contexts. |
| 761 output_offset -= kPointerSize; | 799 output_offset -= kPointerSize; |
| 762 input_offset -= kPointerSize; | 800 input_offset -= kPointerSize; |
| 763 if (is_bottommost) { | 801 if (is_bottommost) { |
| 764 value = input_->GetFrameSlot(input_offset); | 802 value = input_->GetFrameSlot(input_offset); |
| 765 } else { | 803 } else { |
| 766 value = reinterpret_cast<uint32_t>(function->context()); | 804 value = reinterpret_cast<uint32_t>(function->context()); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 941 __ push(eax); | 979 __ push(eax); |
| 942 __ PrepareCallCFunction(1, ebx); | 980 __ PrepareCallCFunction(1, ebx); |
| 943 __ mov(Operand(esp, 0 * kPointerSize), eax); | 981 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 944 { | 982 { |
| 945 AllowExternalCallThatCantCauseGC scope(masm()); | 983 AllowExternalCallThatCantCauseGC scope(masm()); |
| 946 __ CallCFunction( | 984 __ CallCFunction( |
| 947 ExternalReference::compute_output_frames_function(isolate), 1); | 985 ExternalReference::compute_output_frames_function(isolate), 1); |
| 948 } | 986 } |
| 949 __ pop(eax); | 987 __ pop(eax); |
| 950 | 988 |
| 989 if (type() != OSR) { |
| 990 // If frame was dynamically aligned, pop padding. |
| 991 Label no_padding; |
| 992 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
| 993 Immediate(0)); |
| 994 __ j(equal, &no_padding); |
| 995 __ pop(ecx); |
| 996 if (FLAG_debug_code) { |
| 997 __ cmp(ecx, Immediate(kAlignmentZapValue)); |
| 998 __ Assert(equal, "alignment marker expected"); |
| 999 } |
| 1000 __ bind(&no_padding); |
| 1001 } else { |
| 1002 // If frame needs dynamic alignment push padding. |
| 1003 Label no_padding; |
| 1004 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
| 1005 Immediate(0)); |
| 1006 __ j(equal, &no_padding); |
| 1007 __ push(Immediate(kAlignmentZapValue)); |
| 1008 __ bind(&no_padding); |
| 1009 } |
| 1010 |
| 951 // Replace the current frame with the output frames. | 1011 // Replace the current frame with the output frames. |
| 952 Label outer_push_loop, inner_push_loop; | 1012 Label outer_push_loop, inner_push_loop; |
| 953 // Outer loop state: eax = current FrameDescription**, edx = one past the | 1013 // Outer loop state: eax = current FrameDescription**, edx = one past the |
| 954 // last FrameDescription**. | 1014 // last FrameDescription**. |
| 955 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); | 1015 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); |
| 956 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); | 1016 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); |
| 957 __ lea(edx, Operand(eax, edx, times_4, 0)); | 1017 __ lea(edx, Operand(eax, edx, times_4, 0)); |
| 958 __ bind(&outer_push_loop); | 1018 __ bind(&outer_push_loop); |
| 959 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. | 1019 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. |
| 960 __ mov(ebx, Operand(eax, 0)); | 1020 __ mov(ebx, Operand(eax, 0)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 } | 1071 } |
| 1012 __ bind(&done); | 1072 __ bind(&done); |
| 1013 } | 1073 } |
| 1014 | 1074 |
| 1015 #undef __ | 1075 #undef __ |
| 1016 | 1076 |
| 1017 | 1077 |
| 1018 } } // namespace v8::internal | 1078 } } // namespace v8::internal |
| 1019 | 1079 |
| 1020 #endif // V8_TARGET_ARCH_IA32 | 1080 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |