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/deoptimizer.h" | 5 #include "src/deoptimizer.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/ast/prettyprinter.h" | 8 #include "src/ast/prettyprinter.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 output_[index]->GetState()->value())), | 806 output_[index]->GetState()->value())), |
807 has_alignment_padding_ ? "with padding" : "no padding", | 807 has_alignment_padding_ ? "with padding" : "no padding", |
808 ms); | 808 ms); |
809 } | 809 } |
810 } | 810 } |
811 | 811 |
812 | 812 |
813 void Deoptimizer::DoComputeJSFrame(int frame_index) { | 813 void Deoptimizer::DoComputeJSFrame(int frame_index) { |
814 TranslatedFrame* translated_frame = | 814 TranslatedFrame* translated_frame = |
815 &(translated_state_.frames()[frame_index]); | 815 &(translated_state_.frames()[frame_index]); |
| 816 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); |
| 817 |
816 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 818 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
817 int input_index = 0; | 819 int input_index = 0; |
818 | 820 |
819 BailoutId node_id = translated_frame->node_id(); | 821 BailoutId node_id = translated_frame->node_id(); |
820 unsigned height = | 822 unsigned height = |
821 translated_frame->height() - 1; // Do not count the context. | 823 translated_frame->height() - 1; // Do not count the context. |
822 unsigned height_in_bytes = height * kPointerSize; | 824 unsigned height_in_bytes = height * kPointerSize; |
823 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); | 825 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); |
824 value_iterator++; | 826 value_iterator++; |
825 input_index++; | 827 input_index++; |
826 if (trace_scope_ != NULL) { | 828 if (trace_scope_ != NULL) { |
827 PrintF(trace_scope_->file(), " translating frame "); | 829 PrintF(trace_scope_->file(), " translating frame "); |
828 function->PrintName(trace_scope_->file()); | 830 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString(); |
| 831 PrintF(trace_scope_->file(), "%s", name.get()); |
829 PrintF(trace_scope_->file(), | 832 PrintF(trace_scope_->file(), |
830 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); | 833 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); |
831 } | 834 } |
832 | 835 |
833 // The 'fixed' part of the frame consists of the incoming parameters and | 836 // The 'fixed' part of the frame consists of the incoming parameters and |
834 // the part described by JavaScriptFrameConstants. | 837 // the part described by JavaScriptFrameConstants. |
835 unsigned fixed_frame_size = ComputeJavascriptFixedSize(function); | 838 unsigned fixed_frame_size = ComputeJavascriptFixedSize(shared); |
836 unsigned input_frame_size = input_->GetFrameSize(); | 839 unsigned input_frame_size = input_->GetFrameSize(); |
837 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 840 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
838 | 841 |
839 // Allocate and store the output frame description. | 842 // Allocate and store the output frame description. |
840 FrameDescription* output_frame = | 843 FrameDescription* output_frame = |
841 new(output_frame_size) FrameDescription(output_frame_size, function); | 844 new(output_frame_size) FrameDescription(output_frame_size, function); |
842 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); | 845 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
843 | 846 |
844 bool is_bottommost = (0 == frame_index); | 847 bool is_bottommost = (0 == frame_index); |
845 bool is_topmost = (output_count_ - 1 == frame_index); | 848 bool is_topmost = (output_count_ - 1 == frame_index); |
846 CHECK(frame_index >= 0 && frame_index < output_count_); | 849 CHECK(frame_index >= 0 && frame_index < output_count_); |
847 CHECK_NULL(output_[frame_index]); | 850 CHECK_NULL(output_[frame_index]); |
848 output_[frame_index] = output_frame; | 851 output_[frame_index] = output_frame; |
849 | 852 |
850 // The top address for the bottommost output frame can be computed from | 853 // The top address for the bottommost output frame can be computed from |
851 // the input frame pointer and the output frame's height. For all | 854 // the input frame pointer and the output frame's height. For all |
852 // subsequent output frames, it can be computed from the previous one's | 855 // subsequent output frames, it can be computed from the previous one's |
853 // top address and the current frame's size. | 856 // top address and the current frame's size. |
854 Register fp_reg = JavaScriptFrame::fp_register(); | 857 Register fp_reg = JavaScriptFrame::fp_register(); |
855 intptr_t top_address; | 858 intptr_t top_address; |
856 if (is_bottommost) { | 859 if (is_bottommost) { |
857 // Determine whether the input frame contains alignment padding. | 860 // Determine whether the input frame contains alignment padding. |
858 has_alignment_padding_ = | 861 has_alignment_padding_ = |
859 (!compiled_code_->is_turbofanned() && HasAlignmentPadding(function)) | 862 (!compiled_code_->is_turbofanned() && HasAlignmentPadding(shared)) ? 1 |
860 ? 1 | 863 : 0; |
861 : 0; | |
862 // 2 = context and function in the frame. | 864 // 2 = context and function in the frame. |
863 // If the optimized frame had alignment padding, adjust the frame pointer | 865 // If the optimized frame had alignment padding, adjust the frame pointer |
864 // to point to the new position of the old frame pointer after padding | 866 // to point to the new position of the old frame pointer after padding |
865 // is removed. Subtract 2 * kPointerSize for the context and function slots. | 867 // is removed. Subtract 2 * kPointerSize for the context and function slots. |
866 top_address = input_->GetRegister(fp_reg.code()) - | 868 top_address = input_->GetRegister(fp_reg.code()) - |
867 StandardFrameConstants::kFixedFrameSizeFromFp - | 869 StandardFrameConstants::kFixedFrameSizeFromFp - |
868 height_in_bytes + has_alignment_padding_ * kPointerSize; | 870 height_in_bytes + has_alignment_padding_ * kPointerSize; |
869 } else { | 871 } else { |
870 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 872 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
871 } | 873 } |
872 output_frame->SetTop(top_address); | 874 output_frame->SetTop(top_address); |
873 | 875 |
874 // Compute the incoming parameter translation. | 876 // Compute the incoming parameter translation. |
875 int parameter_count = | 877 int parameter_count = shared->internal_formal_parameter_count() + 1; |
876 function->shared()->internal_formal_parameter_count() + 1; | |
877 unsigned output_offset = output_frame_size; | 878 unsigned output_offset = output_frame_size; |
878 unsigned input_offset = input_frame_size; | 879 unsigned input_offset = input_frame_size; |
879 for (int i = 0; i < parameter_count; ++i) { | 880 for (int i = 0; i < parameter_count; ++i) { |
880 output_offset -= kPointerSize; | 881 output_offset -= kPointerSize; |
881 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 882 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
882 output_offset); | 883 output_offset); |
883 } | 884 } |
884 input_offset -= (parameter_count * kPointerSize); | 885 input_offset -= (parameter_count * kPointerSize); |
885 | 886 |
886 // There are no translation commands for the caller's pc and fp, the | 887 // There are no translation commands for the caller's pc and fp, the |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 | 982 |
982 // Translate the rest of the frame. | 983 // Translate the rest of the frame. |
983 for (unsigned i = 0; i < height; ++i) { | 984 for (unsigned i = 0; i < height; ++i) { |
984 output_offset -= kPointerSize; | 985 output_offset -= kPointerSize; |
985 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 986 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
986 output_offset); | 987 output_offset); |
987 } | 988 } |
988 CHECK_EQ(0u, output_offset); | 989 CHECK_EQ(0u, output_offset); |
989 | 990 |
990 // Compute this frame's PC, state, and continuation. | 991 // Compute this frame's PC, state, and continuation. |
991 Code* non_optimized_code = function->shared()->code(); | 992 Code* non_optimized_code = shared->code(); |
992 FixedArray* raw_data = non_optimized_code->deoptimization_data(); | 993 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
993 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); | 994 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
994 Address start = non_optimized_code->instruction_start(); | 995 Address start = non_optimized_code->instruction_start(); |
995 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | 996 unsigned pc_and_state = GetOutputInfo(data, node_id, shared); |
996 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); | 997 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
997 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | 998 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
998 output_frame->SetPc(pc_value); | 999 output_frame->SetPc(pc_value); |
999 | 1000 |
1000 // Update constant pool. | 1001 // Update constant pool. |
1001 if (FLAG_enable_embedded_constant_pool) { | 1002 if (FLAG_enable_embedded_constant_pool) { |
1002 intptr_t constant_pool_value = | 1003 intptr_t constant_pool_value = |
1003 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool()); | 1004 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool()); |
1004 output_frame->SetConstantPool(constant_pool_value); | 1005 output_frame->SetConstantPool(constant_pool_value); |
1005 if (is_topmost) { | 1006 if (is_topmost) { |
(...skipping 20 matching lines...) Expand all Loading... |
1026 } | 1027 } |
1027 output_frame->SetContinuation( | 1028 output_frame->SetContinuation( |
1028 reinterpret_cast<intptr_t>(continuation->entry())); | 1029 reinterpret_cast<intptr_t>(continuation->entry())); |
1029 } | 1030 } |
1030 } | 1031 } |
1031 | 1032 |
1032 | 1033 |
1033 void Deoptimizer::DoComputeInterpretedFrame(int frame_index) { | 1034 void Deoptimizer::DoComputeInterpretedFrame(int frame_index) { |
1034 TranslatedFrame* translated_frame = | 1035 TranslatedFrame* translated_frame = |
1035 &(translated_state_.frames()[frame_index]); | 1036 &(translated_state_.frames()[frame_index]); |
| 1037 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); |
| 1038 |
1036 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 1039 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
1037 int input_index = 0; | 1040 int input_index = 0; |
1038 | 1041 |
1039 BailoutId bytecode_offset = translated_frame->node_id(); | 1042 BailoutId bytecode_offset = translated_frame->node_id(); |
1040 unsigned height = translated_frame->height(); | 1043 unsigned height = translated_frame->height(); |
1041 unsigned height_in_bytes = height * kPointerSize; | 1044 unsigned height_in_bytes = height * kPointerSize; |
1042 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); | 1045 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); |
1043 value_iterator++; | 1046 value_iterator++; |
1044 input_index++; | 1047 input_index++; |
1045 if (trace_scope_ != NULL) { | 1048 if (trace_scope_ != NULL) { |
1046 PrintF(trace_scope_->file(), " translating interpreted frame "); | 1049 PrintF(trace_scope_->file(), " translating interpreted frame "); |
1047 function->PrintName(trace_scope_->file()); | 1050 base::SmartArrayPointer<char> name = shared->DebugName()->ToCString(); |
| 1051 PrintF(trace_scope_->file(), "%s", name.get()); |
1048 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d\n", | 1052 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d\n", |
1049 bytecode_offset.ToInt(), height_in_bytes); | 1053 bytecode_offset.ToInt(), height_in_bytes); |
1050 } | 1054 } |
1051 | 1055 |
1052 // The 'fixed' part of the frame consists of the incoming parameters and | 1056 // The 'fixed' part of the frame consists of the incoming parameters and |
1053 // the part described by InterpreterFrameConstants. | 1057 // the part described by InterpreterFrameConstants. |
1054 unsigned fixed_frame_size = ComputeInterpretedFixedSize(function); | 1058 unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared); |
1055 unsigned input_frame_size = input_->GetFrameSize(); | 1059 unsigned input_frame_size = input_->GetFrameSize(); |
1056 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1060 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
1057 | 1061 |
1058 // Allocate and store the output frame description. | 1062 // Allocate and store the output frame description. |
1059 FrameDescription* output_frame = | 1063 FrameDescription* output_frame = |
1060 new (output_frame_size) FrameDescription(output_frame_size, function); | 1064 new (output_frame_size) FrameDescription(output_frame_size, function); |
1061 output_frame->SetFrameType(StackFrame::INTERPRETED); | 1065 output_frame->SetFrameType(StackFrame::INTERPRETED); |
1062 | 1066 |
1063 bool is_bottommost = (0 == frame_index); | 1067 bool is_bottommost = (0 == frame_index); |
1064 bool is_topmost = (output_count_ - 1 == frame_index); | 1068 bool is_topmost = (output_count_ - 1 == frame_index); |
(...skipping 12 matching lines...) Expand all Loading... |
1077 // new,target and bytecode offset. | 1081 // new,target and bytecode offset. |
1078 top_address = input_->GetRegister(fp_reg.code()) - | 1082 top_address = input_->GetRegister(fp_reg.code()) - |
1079 InterpreterFrameConstants::kFixedFrameSizeFromFp - | 1083 InterpreterFrameConstants::kFixedFrameSizeFromFp - |
1080 height_in_bytes; | 1084 height_in_bytes; |
1081 } else { | 1085 } else { |
1082 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1086 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
1083 } | 1087 } |
1084 output_frame->SetTop(top_address); | 1088 output_frame->SetTop(top_address); |
1085 | 1089 |
1086 // Compute the incoming parameter translation. | 1090 // Compute the incoming parameter translation. |
1087 int parameter_count = | 1091 int parameter_count = shared->internal_formal_parameter_count() + 1; |
1088 function->shared()->internal_formal_parameter_count() + 1; | |
1089 unsigned output_offset = output_frame_size; | 1092 unsigned output_offset = output_frame_size; |
1090 unsigned input_offset = input_frame_size; | 1093 unsigned input_offset = input_frame_size; |
1091 for (int i = 0; i < parameter_count; ++i) { | 1094 for (int i = 0; i < parameter_count; ++i) { |
1092 output_offset -= kPointerSize; | 1095 output_offset -= kPointerSize; |
1093 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 1096 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
1094 output_offset); | 1097 output_offset); |
1095 } | 1098 } |
1096 input_offset -= (parameter_count * kPointerSize); | 1099 input_offset -= (parameter_count * kPointerSize); |
1097 | 1100 |
1098 // There are no translation commands for the caller's pc and fp, the | 1101 // There are no translation commands for the caller's pc and fp, the |
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1974 output_offset; | 1977 output_offset; |
1975 PrintF(trace_scope_->file(), | 1978 PrintF(trace_scope_->file(), |
1976 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s", | 1979 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s", |
1977 reinterpret_cast<intptr_t>(output_address), output_offset, value, | 1980 reinterpret_cast<intptr_t>(output_address), output_offset, value, |
1978 debug_hint_string == nullptr ? "" : debug_hint_string); | 1981 debug_hint_string == nullptr ? "" : debug_hint_string); |
1979 } | 1982 } |
1980 } | 1983 } |
1981 | 1984 |
1982 | 1985 |
1983 unsigned Deoptimizer::ComputeInputFrameSize() const { | 1986 unsigned Deoptimizer::ComputeInputFrameSize() const { |
1984 unsigned fixed_size = ComputeJavascriptFixedSize(function_); | 1987 unsigned fixed_size = StandardFrameConstants::kFixedFrameSize; |
| 1988 if (!function_->IsSmi()) { |
| 1989 fixed_size += ComputeIncomingArgumentSize(function_->shared()); |
| 1990 } else { |
| 1991 CHECK_EQ(Smi::cast(function_), Smi::FromInt(StackFrame::STUB)); |
| 1992 } |
1985 // The fp-to-sp delta already takes the context, constant pool pointer and the | 1993 // The fp-to-sp delta already takes the context, constant pool pointer and the |
1986 // function into account so we have to avoid double counting them. | 1994 // function into account so we have to avoid double counting them. |
1987 unsigned result = fixed_size + fp_to_sp_delta_ - | 1995 unsigned result = fixed_size + fp_to_sp_delta_ - |
1988 StandardFrameConstants::kFixedFrameSizeFromFp; | 1996 StandardFrameConstants::kFixedFrameSizeFromFp; |
1989 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { | 1997 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { |
1990 unsigned stack_slots = compiled_code_->stack_slots(); | 1998 unsigned stack_slots = compiled_code_->stack_slots(); |
1991 unsigned outgoing_size = | 1999 unsigned outgoing_size = |
1992 ComputeOutgoingArgumentSize(compiled_code_, bailout_id_); | 2000 ComputeOutgoingArgumentSize(compiled_code_, bailout_id_); |
1993 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); | 2001 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); |
1994 } | 2002 } |
1995 return result; | 2003 return result; |
1996 } | 2004 } |
1997 | 2005 |
1998 | 2006 // static |
1999 unsigned Deoptimizer::ComputeJavascriptFixedSize(JSFunction* function) const { | 2007 unsigned Deoptimizer::ComputeJavascriptFixedSize(SharedFunctionInfo* shared) { |
2000 // The fixed part of the frame consists of the return address, frame | 2008 // The fixed part of the frame consists of the return address, frame |
2001 // pointer, function, context, and all the incoming arguments. | 2009 // pointer, function, context, and all the incoming arguments. |
2002 return ComputeIncomingArgumentSize(function) + | 2010 return ComputeIncomingArgumentSize(shared) + |
2003 StandardFrameConstants::kFixedFrameSize; | 2011 StandardFrameConstants::kFixedFrameSize; |
2004 } | 2012 } |
2005 | 2013 |
2006 | 2014 // static |
2007 unsigned Deoptimizer::ComputeInterpretedFixedSize(JSFunction* function) const { | 2015 unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) { |
2008 // The fixed part of the frame consists of the return address, frame | 2016 // The fixed part of the frame consists of the return address, frame |
2009 // pointer, function, context, new.target, bytecode offset and all the | 2017 // pointer, function, context, new.target, bytecode offset and all the |
2010 // incoming arguments. | 2018 // incoming arguments. |
2011 return ComputeIncomingArgumentSize(function) + | 2019 return ComputeIncomingArgumentSize(shared) + |
2012 InterpreterFrameConstants::kFixedFrameSize; | 2020 InterpreterFrameConstants::kFixedFrameSize; |
2013 } | 2021 } |
2014 | 2022 |
2015 | 2023 // static |
2016 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { | 2024 unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) { |
2017 // The incoming arguments is the values for formal parameters and | 2025 return (shared->internal_formal_parameter_count() + 1) * kPointerSize; |
2018 // the receiver. Every slot contains a pointer. | |
2019 if (function->IsSmi()) { | |
2020 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); | |
2021 return 0; | |
2022 } | |
2023 unsigned arguments = | |
2024 function->shared()->internal_formal_parameter_count() + 1; | |
2025 return arguments * kPointerSize; | |
2026 } | 2026 } |
2027 | 2027 |
2028 | 2028 |
2029 // static | 2029 // static |
2030 unsigned Deoptimizer::ComputeOutgoingArgumentSize(Code* code, | 2030 unsigned Deoptimizer::ComputeOutgoingArgumentSize(Code* code, |
2031 unsigned bailout_id) { | 2031 unsigned bailout_id) { |
2032 DeoptimizationInputData* data = | 2032 DeoptimizationInputData* data = |
2033 DeoptimizationInputData::cast(code->deoptimization_data()); | 2033 DeoptimizationInputData::cast(code->deoptimization_data()); |
2034 unsigned height = data->ArgumentsStackHeight(bailout_id)->value(); | 2034 unsigned height = data->ArgumentsStackHeight(bailout_id)->value(); |
2035 return height * kPointerSize; | 2035 return height * kPointerSize; |
(...skipping 1663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3699 DCHECK(value_info->IsMaterializedObject()); | 3699 DCHECK(value_info->IsMaterializedObject()); |
3700 | 3700 |
3701 value_info->value_ = | 3701 value_info->value_ = |
3702 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3702 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3703 } | 3703 } |
3704 } | 3704 } |
3705 } | 3705 } |
3706 | 3706 |
3707 } // namespace internal | 3707 } // namespace internal |
3708 } // namespace v8 | 3708 } // namespace v8 |
OLD | NEW |