OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 output_[index]->GetPc(), | 813 output_[index]->GetPc(), |
814 FullCodeGenerator::State2String( | 814 FullCodeGenerator::State2String( |
815 static_cast<FullCodeGenerator::State>( | 815 static_cast<FullCodeGenerator::State>( |
816 output_[index]->GetState()->value())), | 816 output_[index]->GetState()->value())), |
817 has_alignment_padding_ ? "with padding" : "no padding", | 817 has_alignment_padding_ ? "with padding" : "no padding", |
818 ms); | 818 ms); |
819 } | 819 } |
820 } | 820 } |
821 | 821 |
822 | 822 |
| 823 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
| 824 int frame_index) { |
| 825 BailoutId node_id = BailoutId(iterator->Next()); |
| 826 JSFunction* function; |
| 827 if (frame_index != 0) { |
| 828 function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 829 } else { |
| 830 int closure_id = iterator->Next(); |
| 831 USE(closure_id); |
| 832 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
| 833 function = function_; |
| 834 } |
| 835 unsigned height = iterator->Next(); |
| 836 unsigned height_in_bytes = height * kPointerSize; |
| 837 if (trace_) { |
| 838 PrintF(" translating "); |
| 839 function->PrintName(); |
| 840 PrintF(" => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); |
| 841 } |
| 842 |
| 843 // The 'fixed' part of the frame consists of the incoming parameters and |
| 844 // the part described by JavaScriptFrameConstants. |
| 845 unsigned fixed_frame_size = ComputeFixedSize(function); |
| 846 unsigned input_frame_size = input_->GetFrameSize(); |
| 847 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 848 |
| 849 // Allocate and store the output frame description. |
| 850 FrameDescription* output_frame = |
| 851 new(output_frame_size) FrameDescription(output_frame_size, function); |
| 852 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
| 853 |
| 854 bool is_bottommost = (0 == frame_index); |
| 855 bool is_topmost = (output_count_ - 1 == frame_index); |
| 856 ASSERT(frame_index >= 0 && frame_index < output_count_); |
| 857 ASSERT(output_[frame_index] == NULL); |
| 858 output_[frame_index] = output_frame; |
| 859 |
| 860 // The top address for the bottommost output frame can be computed from |
| 861 // the input frame pointer and the output frame's height. For all |
| 862 // subsequent output frames, it can be computed from the previous one's |
| 863 // top address and the current frame's size. |
| 864 Register fp_reg = JavaScriptFrame::fp_register(); |
| 865 intptr_t top_address; |
| 866 if (is_bottommost) { |
| 867 // Determine whether the input frame contains alignment padding. |
| 868 has_alignment_padding_ = HasAlignmentPadding(function) ? 1 : 0; |
| 869 // 2 = context and function in the frame. |
| 870 // If the optimized frame had alignment padding, adjust the frame pointer |
| 871 // to point to the new position of the old frame pointer after padding |
| 872 // is removed. Subtract 2 * kPointerSize for the context and function slots. |
| 873 top_address = input_->GetRegister(fp_reg.code()) - (2 * kPointerSize) - |
| 874 height_in_bytes + has_alignment_padding_ * kPointerSize; |
| 875 } else { |
| 876 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
| 877 } |
| 878 output_frame->SetTop(top_address); |
| 879 |
| 880 // Compute the incoming parameter translation. |
| 881 int parameter_count = function->shared()->formal_parameter_count() + 1; |
| 882 unsigned output_offset = output_frame_size; |
| 883 unsigned input_offset = input_frame_size; |
| 884 for (int i = 0; i < parameter_count; ++i) { |
| 885 output_offset -= kPointerSize; |
| 886 DoTranslateCommand(iterator, frame_index, output_offset); |
| 887 } |
| 888 input_offset -= (parameter_count * kPointerSize); |
| 889 |
| 890 // There are no translation commands for the caller's pc and fp, the |
| 891 // context, and the function. Synthesize their values and set them up |
| 892 // explicitly. |
| 893 // |
| 894 // The caller's pc for the bottommost output frame is the same as in the |
| 895 // input frame. For all subsequent output frames, it can be read from the |
| 896 // previous one. This frame's pc can be computed from the non-optimized |
| 897 // function code and AST id of the bailout. |
| 898 output_offset -= kPointerSize; |
| 899 input_offset -= kPointerSize; |
| 900 intptr_t value; |
| 901 if (is_bottommost) { |
| 902 value = input_->GetFrameSlot(input_offset); |
| 903 } else { |
| 904 value = output_[frame_index - 1]->GetPc(); |
| 905 } |
| 906 output_frame->SetFrameSlot(output_offset, value); |
| 907 if (trace_) { |
| 908 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 909 V8PRIxPTR " ; caller's pc\n", |
| 910 top_address + output_offset, output_offset, value); |
| 911 } |
| 912 |
| 913 // The caller's frame pointer for the bottommost output frame is the same |
| 914 // as in the input frame. For all subsequent output frames, it can be |
| 915 // read from the previous one. Also compute and set this frame's frame |
| 916 // pointer. |
| 917 output_offset -= kPointerSize; |
| 918 input_offset -= kPointerSize; |
| 919 if (is_bottommost) { |
| 920 value = input_->GetFrameSlot(input_offset); |
| 921 } else { |
| 922 value = output_[frame_index - 1]->GetFp(); |
| 923 } |
| 924 output_frame->SetFrameSlot(output_offset, value); |
| 925 intptr_t fp_value = top_address + output_offset; |
| 926 ASSERT(!is_bottommost || (input_->GetRegister(fp_reg.code()) + |
| 927 has_alignment_padding_ * kPointerSize) == fp_value); |
| 928 output_frame->SetFp(fp_value); |
| 929 if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value); |
| 930 if (trace_) { |
| 931 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 932 V8PRIxPTR " ; caller's fp\n", |
| 933 fp_value, output_offset, value); |
| 934 } |
| 935 ASSERT(!is_bottommost || !has_alignment_padding_ || |
| 936 (fp_value & kPointerSize) != 0); |
| 937 |
| 938 // For the bottommost output frame the context can be gotten from the input |
| 939 // frame. For all subsequent output frames it can be gotten from the function |
| 940 // so long as we don't inline functions that need local contexts. |
| 941 Register context_reg = JavaScriptFrame::context_register(); |
| 942 output_offset -= kPointerSize; |
| 943 input_offset -= kPointerSize; |
| 944 if (is_bottommost) { |
| 945 value = input_->GetFrameSlot(input_offset); |
| 946 } else { |
| 947 value = reinterpret_cast<intptr_t>(function->context()); |
| 948 } |
| 949 output_frame->SetFrameSlot(output_offset, value); |
| 950 output_frame->SetContext(value); |
| 951 if (is_topmost) output_frame->SetRegister(context_reg.code(), value); |
| 952 if (trace_) { |
| 953 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 954 V8PRIxPTR "; context\n", |
| 955 top_address + output_offset, output_offset, value); |
| 956 } |
| 957 |
| 958 // The function was mentioned explicitly in the BEGIN_FRAME. |
| 959 output_offset -= kPointerSize; |
| 960 input_offset -= kPointerSize; |
| 961 value = reinterpret_cast<intptr_t>(function); |
| 962 // The function for the bottommost output frame should also agree with the |
| 963 // input frame. |
| 964 ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value); |
| 965 output_frame->SetFrameSlot(output_offset, value); |
| 966 if (trace_) { |
| 967 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
| 968 V8PRIxPTR "; function\n", |
| 969 top_address + output_offset, output_offset, value); |
| 970 } |
| 971 |
| 972 // Translate the rest of the frame. |
| 973 for (unsigned i = 0; i < height; ++i) { |
| 974 output_offset -= kPointerSize; |
| 975 DoTranslateCommand(iterator, frame_index, output_offset); |
| 976 } |
| 977 ASSERT(0 == output_offset); |
| 978 |
| 979 // Compute this frame's PC, state, and continuation. |
| 980 Code* non_optimized_code = function->shared()->code(); |
| 981 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
| 982 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
| 983 Address start = non_optimized_code->instruction_start(); |
| 984 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
| 985 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
| 986 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
| 987 output_frame->SetPc(pc_value); |
| 988 |
| 989 FullCodeGenerator::State state = |
| 990 FullCodeGenerator::StateField::decode(pc_and_state); |
| 991 output_frame->SetState(Smi::FromInt(state)); |
| 992 |
| 993 // Set the continuation for the topmost frame. |
| 994 if (is_topmost && bailout_type_ != DEBUGGER) { |
| 995 Builtins* builtins = isolate_->builtins(); |
| 996 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
| 997 if (bailout_type_ == LAZY) { |
| 998 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| 999 } else if (bailout_type_ == SOFT) { |
| 1000 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
| 1001 } else { |
| 1002 ASSERT(bailout_type_ == EAGER); |
| 1003 } |
| 1004 output_frame->SetContinuation( |
| 1005 reinterpret_cast<intptr_t>(continuation->entry())); |
| 1006 } |
| 1007 } |
| 1008 |
| 1009 |
823 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 1010 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
824 int frame_index) { | 1011 int frame_index) { |
825 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 1012 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
826 unsigned height = iterator->Next(); | 1013 unsigned height = iterator->Next(); |
827 unsigned height_in_bytes = height * kPointerSize; | 1014 unsigned height_in_bytes = height * kPointerSize; |
828 if (trace_) { | 1015 if (trace_) { |
829 PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes); | 1016 PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes); |
830 } | 1017 } |
831 | 1018 |
832 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; | 1019 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; |
(...skipping 1942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2775 | 2962 |
2776 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 2963 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
2777 v->VisitPointer(BitCast<Object**>(&function_)); | 2964 v->VisitPointer(BitCast<Object**>(&function_)); |
2778 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 2965 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
2779 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 2966 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
2780 } | 2967 } |
2781 | 2968 |
2782 #endif // ENABLE_DEBUGGER_SUPPORT | 2969 #endif // ENABLE_DEBUGGER_SUPPORT |
2783 | 2970 |
2784 } } // namespace v8::internal | 2971 } } // namespace v8::internal |
OLD | NEW |