OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/frames.h" | 5 #include "src/frames.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 DCHECK(frames->length() == 0); | 884 DCHECK(frames->length() == 0); |
885 DCHECK(is_optimized()); | 885 DCHECK(is_optimized()); |
886 | 886 |
887 // Delegate to JS frame in absence of turbofan deoptimization. | 887 // Delegate to JS frame in absence of turbofan deoptimization. |
888 // TODO(turbofan): Revisit once we support deoptimization across the board. | 888 // TODO(turbofan): Revisit once we support deoptimization across the board. |
889 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() && | 889 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() && |
890 !FLAG_turbo_asm_deoptimization) { | 890 !FLAG_turbo_asm_deoptimization) { |
891 return JavaScriptFrame::Summarize(frames); | 891 return JavaScriptFrame::Summarize(frames); |
892 } | 892 } |
893 | 893 |
| 894 DisallowHeapAllocation no_gc; |
| 895 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
| 896 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index); |
| 897 FixedArray* const literal_array = data->LiteralArray(); |
| 898 |
| 899 TranslationIterator it(data->TranslationByteArray(), |
| 900 data->TranslationIndex(deopt_index)->value()); |
| 901 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 902 DCHECK_EQ(Translation::BEGIN, opcode); |
| 903 it.Next(); // Drop frame count. |
| 904 int jsframe_count = it.Next(); |
| 905 |
894 // We create the summary in reverse order because the frames | 906 // We create the summary in reverse order because the frames |
895 // in the deoptimization translation are ordered bottom-to-top. | 907 // in the deoptimization translation are ordered bottom-to-top. |
896 DisallowHeapAllocation no_gc; | |
897 TranslatedState state(this); | |
898 bool is_constructor = IsConstructor(); | 908 bool is_constructor = IsConstructor(); |
899 for (TranslatedFrame& frame : state) { | 909 while (jsframe_count != 0) { |
900 switch (frame.kind()) { | 910 opcode = static_cast<Translation::Opcode>(it.Next()); |
901 case TranslatedFrame::kFunction: { | 911 if (opcode == Translation::JS_FRAME) { |
902 BailoutId const ast_id = frame.node_id(); | 912 jsframe_count--; |
903 TranslatedFrame::iterator it = frame.begin(); | 913 BailoutId const ast_id = BailoutId(it.Next()); |
| 914 SharedFunctionInfo* const shared_info = |
| 915 SharedFunctionInfo::cast(literal_array->get(it.Next())); |
| 916 it.Next(); // Skip height. |
904 | 917 |
905 // Get the correct function in the optimized frame. | 918 // The translation commands are ordered and the function is always |
906 JSFunction* function = JSFunction::cast(it->GetRawValue()); | 919 // at the first position, and the receiver is next. |
907 it++; | 920 opcode = static_cast<Translation::Opcode>(it.Next()); |
908 | 921 |
909 // Get the correct receiver in the optimized frame. | 922 // Get the correct function in the optimized frame. |
910 Object* receiver = it->GetRawValue(); | 923 JSFunction* function; |
911 if (receiver == isolate()->heap()->arguments_marker()) { | 924 if (opcode == Translation::LITERAL) { |
912 // TODO(jarin): Materializing a captured object (or duplicated | 925 function = JSFunction::cast(literal_array->get(it.Next())); |
913 // object) is hard, we return undefined for now. This breaks the | 926 } else if (opcode == Translation::STACK_SLOT) { |
914 // produced stack trace, as constructor frames aren't marked as | 927 function = JSFunction::cast(StackSlotAt(it.Next())); |
915 // such anymore. | 928 } else { |
916 receiver = isolate()->heap()->undefined_value(); | 929 CHECK_EQ(Translation::JS_FRAME_FUNCTION, opcode); |
917 } | 930 function = this->function(); |
| 931 } |
| 932 DCHECK_EQ(shared_info, function->shared()); |
918 | 933 |
919 Code* code = function->shared()->code(); | 934 // If we are at a call, the receiver is always in a stack slot. |
920 DeoptimizationOutputData* output_data = | 935 // Otherwise we are not guaranteed to get the receiver value. |
921 DeoptimizationOutputData::cast(code->deoptimization_data()); | 936 opcode = static_cast<Translation::Opcode>(it.Next()); |
922 unsigned entry = | |
923 Deoptimizer::GetOutputInfo(output_data, ast_id, function->shared()); | |
924 unsigned pc_offset = | |
925 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; | |
926 DCHECK(pc_offset > 0); | |
927 | 937 |
928 FrameSummary summary(receiver, function, code, pc_offset, | 938 // Get the correct receiver in the optimized frame. |
929 is_constructor); | 939 Object* receiver; |
930 frames->Add(summary); | 940 if (opcode == Translation::LITERAL) { |
931 is_constructor = false; | 941 receiver = literal_array->get(it.Next()); |
932 break; | 942 } else if (opcode == Translation::STACK_SLOT) { |
| 943 receiver = StackSlotAt(it.Next()); |
| 944 } else if (opcode == Translation::JS_FRAME_FUNCTION) { |
| 945 receiver = this->function(); |
| 946 } else { |
| 947 // The receiver is not in a stack slot nor in a literal. We give up. |
| 948 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| 949 // TODO(3029): Materializing a captured object (or duplicated |
| 950 // object) is hard, we return undefined for now. This breaks the |
| 951 // produced stack trace, as constructor frames aren't marked as |
| 952 // such anymore. |
| 953 receiver = isolate()->heap()->undefined_value(); |
933 } | 954 } |
934 | 955 |
935 case TranslatedFrame::kConstructStub: { | 956 Code* const code = shared_info->code(); |
936 // The next encountered JS_FRAME will be marked as a constructor call. | 957 DeoptimizationOutputData* const output_data = |
937 DCHECK(!is_constructor); | 958 DeoptimizationOutputData::cast(code->deoptimization_data()); |
938 is_constructor = true; | 959 unsigned const entry = |
939 break; | 960 Deoptimizer::GetOutputInfo(output_data, ast_id, shared_info); |
940 } | 961 unsigned const pc_offset = |
| 962 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; |
| 963 DCHECK_NE(0, pc_offset); |
941 | 964 |
942 case TranslatedFrame::kInvalid: | 965 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); |
943 UNREACHABLE(); | 966 frames->Add(summary); |
944 case TranslatedFrame::kArgumentsAdaptor: | 967 is_constructor = false; |
945 case TranslatedFrame::kCompiledStub: | 968 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { |
946 case TranslatedFrame::kGetter: | 969 // The next encountered JS_FRAME will be marked as a constructor call. |
947 case TranslatedFrame::kSetter: | 970 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
948 break; | 971 DCHECK(!is_constructor); |
| 972 is_constructor = true; |
| 973 } else { |
| 974 // Skip over operands to advance to the next opcode. |
| 975 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
949 } | 976 } |
950 } | 977 } |
951 DCHECK(!is_constructor); | 978 DCHECK(!is_constructor); |
952 } | 979 } |
953 | 980 |
954 | 981 |
955 int OptimizedFrame::LookupExceptionHandlerInTable( | 982 int OptimizedFrame::LookupExceptionHandlerInTable( |
956 int* stack_slots, HandlerTable::CatchPrediction* prediction) { | 983 int* stack_slots, HandlerTable::CatchPrediction* prediction) { |
957 Code* code = LookupCode(); | 984 Code* code = LookupCode(); |
958 DCHECK(code->is_optimized_code()); | 985 DCHECK(code->is_optimized_code()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 DCHECK(is_optimized()); | 1020 DCHECK(is_optimized()); |
994 | 1021 |
995 // Delegate to JS frame in absence of turbofan deoptimization. | 1022 // Delegate to JS frame in absence of turbofan deoptimization. |
996 // TODO(turbofan): Revisit once we support deoptimization across the board. | 1023 // TODO(turbofan): Revisit once we support deoptimization across the board. |
997 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() && | 1024 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() && |
998 !FLAG_turbo_asm_deoptimization) { | 1025 !FLAG_turbo_asm_deoptimization) { |
999 return JavaScriptFrame::GetFunctions(functions); | 1026 return JavaScriptFrame::GetFunctions(functions); |
1000 } | 1027 } |
1001 | 1028 |
1002 DisallowHeapAllocation no_gc; | 1029 DisallowHeapAllocation no_gc; |
1003 TranslatedState state(this); | 1030 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
1004 for (TranslatedFrame const& frame : state) { | 1031 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index); |
1005 if (frame.kind() == TranslatedFrame::kFunction) { | 1032 FixedArray* const literal_array = data->LiteralArray(); |
1006 functions->Add(JSFunction::cast(frame.front().GetRawValue())); | 1033 |
| 1034 TranslationIterator it(data->TranslationByteArray(), |
| 1035 data->TranslationIndex(deopt_index)->value()); |
| 1036 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
| 1037 DCHECK_EQ(Translation::BEGIN, opcode); |
| 1038 it.Next(); // Skip frame count. |
| 1039 int jsframe_count = it.Next(); |
| 1040 |
| 1041 // We insert the frames in reverse order because the frames |
| 1042 // in the deoptimization translation are ordered bottom-to-top. |
| 1043 while (jsframe_count != 0) { |
| 1044 opcode = static_cast<Translation::Opcode>(it.Next()); |
| 1045 // Skip over operands to advance to the next opcode. |
| 1046 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
| 1047 if (opcode == Translation::JS_FRAME) { |
| 1048 jsframe_count--; |
| 1049 |
| 1050 // The translation commands are ordered and the function is always at the |
| 1051 // first position. |
| 1052 opcode = static_cast<Translation::Opcode>(it.Next()); |
| 1053 |
| 1054 // Get the correct function in the optimized frame. |
| 1055 Object* function; |
| 1056 if (opcode == Translation::LITERAL) { |
| 1057 function = literal_array->get(it.Next()); |
| 1058 } else if (opcode == Translation::STACK_SLOT) { |
| 1059 function = StackSlotAt(it.Next()); |
| 1060 } else { |
| 1061 CHECK_EQ(Translation::JS_FRAME_FUNCTION, opcode); |
| 1062 function = this->function(); |
| 1063 } |
| 1064 functions->Add(JSFunction::cast(function)); |
1007 } | 1065 } |
1008 } | 1066 } |
1009 } | 1067 } |
1010 | 1068 |
1011 | 1069 |
| 1070 Object* OptimizedFrame::StackSlotAt(int index) const { |
| 1071 // Positive index means the value is spilled to the locals |
| 1072 // area. Negative means it is stored in the incoming parameter |
| 1073 // area. |
| 1074 if (index >= 0) return GetExpression(index); |
| 1075 |
| 1076 // Index -1 overlaps with last parameter, -n with the first parameter, |
| 1077 // (-n - 1) with the receiver with n being the number of parameters |
| 1078 // of the outermost, optimized frame. |
| 1079 int const parameter_count = ComputeParametersCount(); |
| 1080 int const parameter_index = index + parameter_count; |
| 1081 return (parameter_index == -1) ? receiver() : GetParameter(parameter_index); |
| 1082 } |
| 1083 |
| 1084 |
1012 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { | 1085 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { |
1013 return Smi::cast(GetExpression(0))->value(); | 1086 return Smi::cast(GetExpression(0))->value(); |
1014 } | 1087 } |
1015 | 1088 |
1016 | 1089 |
1017 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { | 1090 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { |
1018 return fp() + StandardFrameConstants::kCallerSPOffset; | 1091 return fp() + StandardFrameConstants::kCallerSPOffset; |
1019 } | 1092 } |
1020 | 1093 |
1021 | 1094 |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1524 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1452 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1525 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1453 list.Add(frame, zone); | 1526 list.Add(frame, zone); |
1454 } | 1527 } |
1455 return list.ToVector(); | 1528 return list.ToVector(); |
1456 } | 1529 } |
1457 | 1530 |
1458 | 1531 |
1459 } // namespace internal | 1532 } // namespace internal |
1460 } // namespace v8 | 1533 } // namespace v8 |
OLD | NEW |