OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 return result; | 116 return result; |
117 } | 117 } |
118 | 118 |
119 | 119 |
120 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { | 120 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { |
121 if (jsframe_index == 0) return 0; | 121 if (jsframe_index == 0) return 0; |
122 | 122 |
123 int frame_index = 0; | 123 int frame_index = 0; |
124 while (jsframe_index >= 0) { | 124 while (jsframe_index >= 0) { |
125 FrameDescription* frame = output_[frame_index]; | 125 FrameDescription* frame = output_[frame_index]; |
126 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { | 126 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT || |
127 frame->GetFrameType() == StackFrame::OPTIMIZED) { | |
127 jsframe_index--; | 128 jsframe_index--; |
128 } | 129 } |
129 frame_index++; | 130 frame_index++; |
130 } | 131 } |
131 | 132 |
132 return frame_index - 1; | 133 return frame_index - 1; |
133 } | 134 } |
134 | 135 |
135 | 136 |
136 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | 137 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
592 } | 593 } |
593 } | 594 } |
594 compiled_code_ = FindOptimizedCode(function, optimized_code); | 595 compiled_code_ = FindOptimizedCode(function, optimized_code); |
595 #if DEBUG | 596 #if DEBUG |
596 DCHECK(compiled_code_ != NULL); | 597 DCHECK(compiled_code_ != NULL); |
597 if (type == EAGER || type == SOFT || type == LAZY) { | 598 if (type == EAGER || type == SOFT || type == LAZY) { |
598 DCHECK(compiled_code_->kind() != Code::FUNCTION); | 599 DCHECK(compiled_code_->kind() != Code::FUNCTION); |
599 } | 600 } |
600 #endif | 601 #endif |
601 | 602 |
602 StackFrame::Type frame_type = function == NULL | 603 StackFrame::Type frame_type = |
603 ? StackFrame::STUB | 604 function == NULL ? StackFrame::STUB : StackFrame::OPTIMIZED; |
604 : StackFrame::JAVA_SCRIPT; | |
605 trace_scope_ = TraceEnabledFor(type, frame_type) ? | 605 trace_scope_ = TraceEnabledFor(type, frame_type) ? |
606 new CodeTracer::Scope(isolate->GetCodeTracer()) : NULL; | 606 new CodeTracer::Scope(isolate->GetCodeTracer()) : NULL; |
607 #ifdef DEBUG | 607 #ifdef DEBUG |
608 CHECK(AllowHeapAllocation::IsAllowed()); | 608 CHECK(AllowHeapAllocation::IsAllowed()); |
609 disallow_heap_allocation_ = new DisallowHeapAllocation(); | 609 disallow_heap_allocation_ = new DisallowHeapAllocation(); |
610 #endif // DEBUG | 610 #endif // DEBUG |
611 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { | 611 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { |
612 PROFILE(isolate_, CodeDeoptEvent(compiled_code_, bailout_id_, from_, | 612 PROFILE(isolate_, CodeDeoptEvent(compiled_code_, bailout_id_, from_, |
613 fp_to_sp_delta_)); | 613 fp_to_sp_delta_)); |
614 } | 614 } |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
880 unsigned height_in_bytes = height * kPointerSize; | 880 unsigned height_in_bytes = height * kPointerSize; |
881 if (trace_scope_ != NULL) { | 881 if (trace_scope_ != NULL) { |
882 PrintF(trace_scope_->file(), " translating "); | 882 PrintF(trace_scope_->file(), " translating "); |
883 function->PrintName(trace_scope_->file()); | 883 function->PrintName(trace_scope_->file()); |
884 PrintF(trace_scope_->file(), | 884 PrintF(trace_scope_->file(), |
885 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); | 885 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); |
886 } | 886 } |
887 | 887 |
888 // The 'fixed' part of the frame consists of the incoming parameters and | 888 // The 'fixed' part of the frame consists of the incoming parameters and |
889 // the part described by JavaScriptFrameConstants. | 889 // the part described by JavaScriptFrameConstants. |
890 unsigned fixed_frame_size = ComputeFixedSize(function); | 890 unsigned fixed_frame_size = ComputeFixedSize(function, true); |
891 unsigned input_frame_size = input_->GetFrameSize(); | 891 unsigned input_frame_size = input_->GetFrameSize(); |
892 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 892 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
893 | 893 |
894 // Allocate and store the output frame description. | 894 // Allocate and store the output frame description. |
895 FrameDescription* output_frame = | 895 FrameDescription* output_frame = |
896 new(output_frame_size) FrameDescription(output_frame_size, function); | 896 new(output_frame_size) FrameDescription(output_frame_size, function); |
897 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); | 897 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
898 | 898 |
899 bool is_bottommost = (0 == frame_index); | 899 bool is_bottommost = (0 == frame_index); |
900 bool is_topmost = (output_count_ - 1 == frame_index); | 900 bool is_topmost = (output_count_ - 1 == frame_index); |
901 CHECK(frame_index >= 0 && frame_index < output_count_); | 901 CHECK(frame_index >= 0 && frame_index < output_count_); |
902 CHECK_NULL(output_[frame_index]); | 902 CHECK_NULL(output_[frame_index]); |
903 output_[frame_index] = output_frame; | 903 output_[frame_index] = output_frame; |
904 | 904 |
905 // The top address for the bottommost output frame can be computed from | 905 // The top address for the bottommost output frame can be computed from |
906 // the input frame pointer and the output frame's height. For all | 906 // the input frame pointer and the output frame's height. For all |
907 // subsequent output frames, it can be computed from the previous one's | 907 // subsequent output frames, it can be computed from the previous one's |
908 // top address and the current frame's size. | 908 // top address and the current frame's size. |
909 Register fp_reg = JavaScriptFrame::fp_register(); | 909 Register fp_reg = JavaScriptFrame::fp_register(); |
910 intptr_t top_address; | 910 intptr_t top_address; |
911 if (is_bottommost) { | 911 if (is_bottommost) { |
912 // Determine whether the input frame contains alignment padding. | 912 // Determine whether the input frame contains alignment padding. |
913 has_alignment_padding_ = | 913 has_alignment_padding_ = |
914 (!compiled_code_->is_turbofanned() && HasAlignmentPadding(function)) | 914 (!compiled_code_->is_turbofanned() && HasAlignmentPadding(function)) |
915 ? 1 | 915 ? 1 |
916 : 0; | 916 : 0; |
917 // 2 = context and function in the frame. | 917 // 2 = context and function in the frame. |
918 // If the optimized frame had alignment padding, adjust the frame pointer | 918 // If the optimized frame had alignment padding, adjust the frame pointer |
919 // to point to the new position of the old frame pointer after padding | 919 // to point to the new position of the old frame pointer after padding |
920 // is removed. Subtract 2 * kPointerSize for the context and function slots. | 920 // is removed. Subtract the fixed frame size. |
921 top_address = input_->GetRegister(fp_reg.code()) - | 921 top_address = input_->GetRegister(fp_reg.code()) - |
922 StandardFrameConstants::kFixedFrameSizeFromFp - | 922 JavaScriptFrameConstants::kUnoptimizedFixedFrameSizeFromFp - |
923 height_in_bytes + has_alignment_padding_ * kPointerSize; | 923 height_in_bytes + has_alignment_padding_ * kPointerSize; |
924 } else { | 924 } else { |
925 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 925 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
926 } | 926 } |
927 output_frame->SetTop(top_address); | 927 output_frame->SetTop(top_address); |
928 | 928 |
929 // Compute the incoming parameter translation. | 929 // Compute the incoming parameter translation. |
930 int parameter_count = | 930 int parameter_count = |
931 function->shared()->internal_formal_parameter_count() + 1; | 931 function->shared()->internal_formal_parameter_count() + 1; |
932 unsigned output_offset = output_frame_size; | 932 unsigned output_offset = output_frame_size; |
933 unsigned input_offset = input_frame_size; | 933 unsigned input_offset = input_frame_size; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1047 // input frame. | 1047 // input frame. |
1048 DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value); | 1048 DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value); |
1049 output_frame->SetFrameSlot(output_offset, value); | 1049 output_frame->SetFrameSlot(output_offset, value); |
1050 if (trace_scope_ != NULL) { | 1050 if (trace_scope_ != NULL) { |
1051 PrintF(trace_scope_->file(), | 1051 PrintF(trace_scope_->file(), |
1052 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1052 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
1053 V8PRIxPTR "; function\n", | 1053 V8PRIxPTR "; function\n", |
1054 top_address + output_offset, output_offset, value); | 1054 top_address + output_offset, output_offset, value); |
1055 } | 1055 } |
1056 | 1056 |
1057 // The type feedback vector must be retrieved from the function, as it's | |
1058 // not available in the input frame. | |
1059 output_offset -= kPointerSize; | |
1060 TypeFeedbackVector* vector = function->shared()->feedback_vector(); | |
1061 value = reinterpret_cast<intptr_t>(vector); | |
1062 output_frame->SetFrameSlot(output_offset, value); | |
1063 if (trace_scope_ != NULL) { | |
1064 PrintF(trace_scope_->file(), | |
1065 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR "; vector\n", | |
1066 top_address + output_offset, output_offset, value); | |
1067 } | |
1068 | |
1057 // Translate the rest of the frame. | 1069 // Translate the rest of the frame. |
1058 for (unsigned i = 0; i < height; ++i) { | 1070 for (unsigned i = 0; i < height; ++i) { |
1059 output_offset -= kPointerSize; | 1071 output_offset -= kPointerSize; |
1060 DoTranslateCommand(iterator, frame_index, output_offset); | 1072 DoTranslateCommand(iterator, frame_index, output_offset); |
1061 } | 1073 } |
1062 CHECK_EQ(0u, output_offset); | 1074 CHECK_EQ(0u, output_offset); |
1063 | 1075 |
1064 // Compute this frame's PC, state, and continuation. | 1076 // Compute this frame's PC, state, and continuation. |
1065 Code* non_optimized_code = function->shared()->code(); | 1077 Code* non_optimized_code = function->shared()->code(); |
1066 FixedArray* raw_data = non_optimized_code->deoptimization_data(); | 1078 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
(...skipping 1636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2703 StandardFrameConstants::kFixedFrameSizeFromFp; | 2715 StandardFrameConstants::kFixedFrameSizeFromFp; |
2704 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { | 2716 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { |
2705 unsigned stack_slots = compiled_code_->stack_slots(); | 2717 unsigned stack_slots = compiled_code_->stack_slots(); |
2706 unsigned outgoing_size = ComputeOutgoingArgumentSize(); | 2718 unsigned outgoing_size = ComputeOutgoingArgumentSize(); |
2707 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); | 2719 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); |
2708 } | 2720 } |
2709 return result; | 2721 return result; |
2710 } | 2722 } |
2711 | 2723 |
2712 | 2724 |
2713 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { | 2725 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function, |
2726 bool unoptimized_frame) const { | |
2714 // The fixed part of the frame consists of the return address, frame | 2727 // The fixed part of the frame consists of the return address, frame |
2715 // pointer, function, context, and all the incoming arguments. | 2728 // pointer, function, context, and all the incoming arguments. |
2716 return ComputeIncomingArgumentSize(function) + | 2729 return ComputeIncomingArgumentSize(function) + |
2717 StandardFrameConstants::kFixedFrameSize; | 2730 (unoptimized_frame |
2731 ? JavaScriptFrameConstants::kUnoptimizedFixedFrameSize | |
2732 : StandardFrameConstants::kFixedFrameSize); | |
2718 } | 2733 } |
2719 | 2734 |
2720 | 2735 |
2721 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { | 2736 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { |
2722 // The incoming arguments is the values for formal parameters and | 2737 // The incoming arguments is the values for formal parameters and |
2723 // the receiver. Every slot contains a pointer. | 2738 // the receiver. Every slot contains a pointer. |
2724 if (function->IsSmi()) { | 2739 if (function->IsSmi()) { |
2725 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); | 2740 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); |
2726 return 0; | 2741 return 0; |
2727 } | 2742 } |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2833 } | 2848 } |
2834 | 2849 |
2835 // Zap all the slots. | 2850 // Zap all the slots. |
2836 for (unsigned o = 0; o < frame_size; o += kPointerSize) { | 2851 for (unsigned o = 0; o < frame_size; o += kPointerSize) { |
2837 SetFrameSlot(o, kZapUint32); | 2852 SetFrameSlot(o, kZapUint32); |
2838 } | 2853 } |
2839 } | 2854 } |
2840 | 2855 |
2841 | 2856 |
2842 int FrameDescription::ComputeFixedSize() { | 2857 int FrameDescription::ComputeFixedSize() { |
2843 return StandardFrameConstants::kFixedFrameSize + | 2858 // Full-code javascript frames have a type feedback vector. |
2844 (ComputeParametersCount() + 1) * kPointerSize; | 2859 const int fixed_size = |
2860 type_ == StackFrame::JAVA_SCRIPT | |
2861 ? JavaScriptFrameConstants::kUnoptimizedFixedFrameSize | |
2862 : StandardFrameConstants::kFixedFrameSize; | |
2863 return fixed_size + (ComputeParametersCount() + 1) * kPointerSize; | |
2845 } | 2864 } |
2846 | 2865 |
2847 | 2866 |
2848 unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) { | 2867 unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) { |
2849 if (slot_index >= 0) { | 2868 if (slot_index >= 0) { |
2850 // Local or spill slots. Skip the fixed part of the frame | 2869 // Local or spill slots. Skip the fixed part of the frame |
2851 // including all arguments. | 2870 // including all arguments. |
2852 unsigned base = GetFrameSize() - ComputeFixedSize(); | 2871 unsigned base = GetFrameSize() - ComputeFixedSize(); |
2853 return base - ((slot_index + 1) * kPointerSize); | 2872 return base - ((slot_index + 1) * kPointerSize); |
2854 } else { | 2873 } else { |
2855 // Incoming parameter. | 2874 // Incoming parameter. |
2856 int arg_size = (ComputeParametersCount() + 1) * kPointerSize; | 2875 int arg_size = (ComputeParametersCount() + 1) * kPointerSize; |
2857 unsigned base = GetFrameSize() - arg_size; | 2876 unsigned base = GetFrameSize() - arg_size; |
2858 return base - ((slot_index + 1) * kPointerSize); | 2877 return base - ((slot_index + 1) * kPointerSize); |
2859 } | 2878 } |
2860 } | 2879 } |
2861 | 2880 |
2862 | 2881 |
2863 int FrameDescription::ComputeParametersCount() { | 2882 int FrameDescription::ComputeParametersCount() { |
2864 switch (type_) { | 2883 switch (type_) { |
2884 case StackFrame::OPTIMIZED: | |
2865 case StackFrame::JAVA_SCRIPT: | 2885 case StackFrame::JAVA_SCRIPT: |
2866 return function_->shared()->internal_formal_parameter_count(); | 2886 return function_->shared()->internal_formal_parameter_count(); |
2867 case StackFrame::ARGUMENTS_ADAPTOR: { | 2887 case StackFrame::ARGUMENTS_ADAPTOR: { |
2868 // Last slot contains number of incomming arguments as a smi. | 2888 // Last slot contains number of incomming arguments as a smi. |
2869 // Can't use GetExpression(0) because it would cause infinite recursion. | 2889 // Can't use GetExpression(0) because it would cause infinite recursion. |
2870 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); | 2890 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); |
2871 } | 2891 } |
2872 case StackFrame::STUB: | 2892 case StackFrame::STUB: |
2873 return -1; // Minus receiver. | 2893 return -1; // Minus receiver. |
2874 default: | 2894 default: |
2875 FATAL("Unexpected stack frame type"); | 2895 FATAL("Unexpected stack frame type"); |
2876 return 0; | 2896 return 0; |
2877 } | 2897 } |
2878 } | 2898 } |
2879 | 2899 |
2880 | 2900 |
2881 Object* FrameDescription::GetParameter(int index) { | 2901 Object* FrameDescription::GetParameter(int index) { |
2882 CHECK_GE(index, 0); | 2902 CHECK_GE(index, 0); |
2883 CHECK_LT(index, ComputeParametersCount()); | 2903 CHECK_LT(index, ComputeParametersCount()); |
2884 // The slot indexes for incoming arguments are negative. | 2904 // The slot indexes for incoming arguments are negative. |
2885 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); | 2905 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); |
2886 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 2906 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
2887 } | 2907 } |
2888 | 2908 |
2889 | 2909 |
2890 unsigned FrameDescription::GetExpressionCount() { | 2910 unsigned FrameDescription::GetExpressionCount() { |
2891 CHECK_EQ(StackFrame::JAVA_SCRIPT, type_); | 2911 CHECK(type_ == StackFrame::JAVA_SCRIPT || type_ == StackFrame::OPTIMIZED); |
Jarin
2015/02/26 09:22:06
I am quite confused about how we could get StackFr
mvstanton
2015/03/20 12:21:09
Good point, I've fixed it. That change came out of
| |
2892 unsigned size = GetFrameSize() - ComputeFixedSize(); | 2912 unsigned size = GetFrameSize() - ComputeFixedSize(); |
2893 return size / kPointerSize; | 2913 return size / kPointerSize; |
2894 } | 2914 } |
2895 | 2915 |
2896 | 2916 |
2897 Object* FrameDescription::GetExpression(int index) { | 2917 Object* FrameDescription::GetExpression(int index) { |
2898 DCHECK_EQ(StackFrame::JAVA_SCRIPT, type_); | 2918 DCHECK(type_ == StackFrame::JAVA_SCRIPT || type_ == StackFrame::OPTIMIZED); |
2899 unsigned offset = GetOffsetFromSlotIndex(index); | 2919 unsigned offset = GetOffsetFromSlotIndex(index); |
2900 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 2920 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
2901 } | 2921 } |
2902 | 2922 |
2903 | 2923 |
2904 void TranslationBuffer::Add(int32_t value, Zone* zone) { | 2924 void TranslationBuffer::Add(int32_t value, Zone* zone) { |
2905 // Encode the sign bit in the least significant bit. | 2925 // Encode the sign bit in the least significant bit. |
2906 bool is_negative = (value < 0); | 2926 bool is_negative = (value < 0); |
2907 uint32_t bits = ((is_negative ? -value : value) << 1) | | 2927 uint32_t bits = ((is_negative ? -value : value) << 1) | |
2908 static_cast<int32_t>(is_negative); | 2928 static_cast<int32_t>(is_negative); |
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3672 Deoptimizer::GetDeoptimizationId(isolate, info->target_address(), | 3692 Deoptimizer::GetDeoptimizationId(isolate, info->target_address(), |
3673 Deoptimizer::LAZY))) { | 3693 Deoptimizer::LAZY))) { |
3674 CHECK(RelocInfo::IsRuntimeEntry(info->rmode())); | 3694 CHECK(RelocInfo::IsRuntimeEntry(info->rmode())); |
3675 return DeoptInfo(last_position, NULL, last_reason); | 3695 return DeoptInfo(last_position, NULL, last_reason); |
3676 } | 3696 } |
3677 } | 3697 } |
3678 } | 3698 } |
3679 return DeoptInfo(0, NULL, Deoptimizer::kNoReason); | 3699 return DeoptInfo(0, NULL, Deoptimizer::kNoReason); |
3680 } | 3700 } |
3681 } } // namespace v8::internal | 3701 } } // namespace v8::internal |
OLD | NEW |