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/ast/ast.h" | 9 #include "src/ast/ast.h" |
10 #include "src/ast/scopeinfo.h" | 10 #include "src/ast/scopeinfo.h" |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 state->fp = fp; | 610 state->fp = fp; |
611 state->pc_address = ResolveReturnAddressLocation( | 611 state->pc_address = ResolveReturnAddressLocation( |
612 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); | 612 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); |
613 // The constant pool recorded in the exit frame is not associated | 613 // The constant pool recorded in the exit frame is not associated |
614 // with the pc in this state (the return address into a C entry | 614 // with the pc in this state (the return address into a C entry |
615 // stub). ComputeCallerState will retrieve the constant pool | 615 // stub). ComputeCallerState will retrieve the constant pool |
616 // together with the associated caller pc. | 616 // together with the associated caller pc. |
617 state->constant_pool_address = NULL; | 617 state->constant_pool_address = NULL; |
618 } | 618 } |
619 | 619 |
620 void StandardFrame::Summarize(List<FrameSummary>* functions) const { | 620 void StandardFrame::Summarize(List<FrameSummary>* functions, |
| 621 FrameSummary::Mode mode) const { |
621 DCHECK(functions->length() == 0); | 622 DCHECK(functions->length() == 0); |
622 // default implementation: no summary added | 623 // default implementation: no summary added |
623 } | 624 } |
624 | 625 |
625 JSFunction* StandardFrame::function() const { | 626 JSFunction* StandardFrame::function() const { |
626 // this default implementation is overridden by JS and WASM frames | 627 // this default implementation is overridden by JS and WASM frames |
627 return nullptr; | 628 return nullptr; |
628 } | 629 } |
629 | 630 |
630 Object* StandardFrame::receiver() const { | 631 Object* StandardFrame::receiver() const { |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 Address JavaScriptFrame::GetCallerStackPointer() const { | 854 Address JavaScriptFrame::GetCallerStackPointer() const { |
854 return fp() + StandardFrameConstants::kCallerSPOffset; | 855 return fp() + StandardFrameConstants::kCallerSPOffset; |
855 } | 856 } |
856 | 857 |
857 | 858 |
858 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const { | 859 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const { |
859 DCHECK(functions->length() == 0); | 860 DCHECK(functions->length() == 0); |
860 functions->Add(function()); | 861 functions->Add(function()); |
861 } | 862 } |
862 | 863 |
863 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) const { | 864 void JavaScriptFrame::Summarize(List<FrameSummary>* functions, |
| 865 FrameSummary::Mode mode) const { |
864 DCHECK(functions->length() == 0); | 866 DCHECK(functions->length() == 0); |
865 Code* code = LookupCode(); | 867 Code* code = LookupCode(); |
866 int offset = static_cast<int>(pc() - code->instruction_start()); | 868 int offset = static_cast<int>(pc() - code->instruction_start()); |
867 AbstractCode* abstract_code = AbstractCode::cast(code); | 869 AbstractCode* abstract_code = AbstractCode::cast(code); |
868 FrameSummary summary(receiver(), function(), abstract_code, offset, | 870 FrameSummary summary(receiver(), function(), abstract_code, offset, |
869 IsConstructor()); | 871 IsConstructor(), mode); |
870 functions->Add(summary); | 872 functions->Add(summary); |
871 } | 873 } |
872 | 874 |
873 JSFunction* JavaScriptFrame::function() const { | 875 JSFunction* JavaScriptFrame::function() const { |
874 return JSFunction::cast(function_slot_object()); | 876 return JSFunction::cast(function_slot_object()); |
875 } | 877 } |
876 | 878 |
877 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } | 879 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } |
878 | 880 |
879 int JavaScriptFrame::LookupExceptionHandlerInTable( | 881 int JavaScriptFrame::LookupExceptionHandlerInTable( |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 | 961 |
960 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) { | 962 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) { |
961 return code->is_turbofanned() && function->shared()->asm_function() && | 963 return code->is_turbofanned() && function->shared()->asm_function() && |
962 !FLAG_turbo_asm_deoptimization; | 964 !FLAG_turbo_asm_deoptimization; |
963 } | 965 } |
964 | 966 |
965 } // namespace | 967 } // namespace |
966 | 968 |
967 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, | 969 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, |
968 AbstractCode* abstract_code, int code_offset, | 970 AbstractCode* abstract_code, int code_offset, |
969 bool is_constructor) | 971 bool is_constructor, Mode mode) |
970 : receiver_(receiver, function->GetIsolate()), | 972 : receiver_(receiver, function->GetIsolate()), |
971 function_(function), | 973 function_(function), |
972 abstract_code_(abstract_code), | 974 abstract_code_(abstract_code), |
973 code_offset_(code_offset), | 975 code_offset_(code_offset), |
974 is_constructor_(is_constructor) { | 976 is_constructor_(is_constructor) { |
975 DCHECK(abstract_code->IsBytecodeArray() || | 977 DCHECK(abstract_code->IsBytecodeArray() || |
976 Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION || | 978 Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION || |
977 CannotDeoptFromAsmCode(Code::cast(abstract_code), function)); | 979 CannotDeoptFromAsmCode(Code::cast(abstract_code), function) || |
| 980 mode == kApproximateSummary); |
978 } | 981 } |
979 | 982 |
980 FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) { | 983 FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) { |
981 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 984 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
982 frame->Summarize(&frames); | 985 frame->Summarize(&frames); |
983 return frames.first(); | 986 return frames.first(); |
984 } | 987 } |
985 | 988 |
986 void FrameSummary::Print() { | 989 void FrameSummary::Print() { |
987 PrintF("receiver: "); | 990 PrintF("receiver: "); |
988 receiver_->ShortPrint(); | 991 receiver_->ShortPrint(); |
989 PrintF("\nfunction: "); | 992 PrintF("\nfunction: "); |
990 function_->shared()->DebugName()->ShortPrint(); | 993 function_->shared()->DebugName()->ShortPrint(); |
991 PrintF("\ncode: "); | 994 PrintF("\ncode: "); |
992 abstract_code_->ShortPrint(); | 995 abstract_code_->ShortPrint(); |
993 if (abstract_code_->IsCode()) { | 996 if (abstract_code_->IsCode()) { |
994 Code* code = abstract_code_->GetCode(); | 997 Code* code = abstract_code_->GetCode(); |
995 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT "); | 998 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT "); |
996 if (code->kind() == Code::OPTIMIZED_FUNCTION) { | 999 if (code->kind() == Code::OPTIMIZED_FUNCTION) { |
997 DCHECK(CannotDeoptFromAsmCode(code, *function())); | 1000 if (function()->shared()->asm_function()) { |
998 PrintF(" ASM "); | 1001 DCHECK(CannotDeoptFromAsmCode(code, *function())); |
| 1002 PrintF(" ASM "); |
| 1003 } else { |
| 1004 PrintF(" OPT (approximate)"); |
| 1005 } |
999 } | 1006 } |
1000 } else { | 1007 } else { |
1001 PrintF(" BYTECODE "); | 1008 PrintF(" BYTECODE "); |
1002 } | 1009 } |
1003 PrintF("\npc: %d\n", code_offset_); | 1010 PrintF("\npc: %d\n", code_offset_); |
1004 } | 1011 } |
1005 | 1012 |
1006 void OptimizedFrame::Summarize(List<FrameSummary>* frames) const { | 1013 void OptimizedFrame::Summarize(List<FrameSummary>* frames, |
| 1014 FrameSummary::Mode mode) const { |
1007 DCHECK(frames->length() == 0); | 1015 DCHECK(frames->length() == 0); |
1008 DCHECK(is_optimized()); | 1016 DCHECK(is_optimized()); |
1009 | 1017 |
1010 // Delegate to JS frame in absence of turbofan deoptimization. | 1018 // Delegate to JS frame in absence of turbofan deoptimization. |
1011 // TODO(turbofan): Revisit once we support deoptimization across the board. | 1019 // TODO(turbofan): Revisit once we support deoptimization across the board. |
1012 Code* code = LookupCode(); | 1020 Code* code = LookupCode(); |
1013 if (code->kind() == Code::BUILTIN || | 1021 if (code->kind() == Code::BUILTIN || |
1014 CannotDeoptFromAsmCode(code, function())) { | 1022 CannotDeoptFromAsmCode(code, function())) { |
1015 return JavaScriptFrame::Summarize(frames); | 1023 return JavaScriptFrame::Summarize(frames); |
1016 } | 1024 } |
1017 | 1025 |
1018 DisallowHeapAllocation no_gc; | 1026 DisallowHeapAllocation no_gc; |
1019 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 1027 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
1020 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index); | 1028 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index); |
| 1029 if (deopt_index == Safepoint::kNoDeoptimizationIndex) { |
| 1030 DCHECK(data == nullptr); |
| 1031 if (mode == FrameSummary::kApproximateSummary) { |
| 1032 return JavaScriptFrame::Summarize(frames, mode); |
| 1033 } |
| 1034 FATAL("Missing deoptimization information for OptimizedFrame::Summarize."); |
| 1035 } |
1021 FixedArray* const literal_array = data->LiteralArray(); | 1036 FixedArray* const literal_array = data->LiteralArray(); |
1022 | 1037 |
1023 TranslationIterator it(data->TranslationByteArray(), | 1038 TranslationIterator it(data->TranslationByteArray(), |
1024 data->TranslationIndex(deopt_index)->value()); | 1039 data->TranslationIndex(deopt_index)->value()); |
1025 Translation::Opcode frame_opcode = | 1040 Translation::Opcode frame_opcode = |
1026 static_cast<Translation::Opcode>(it.Next()); | 1041 static_cast<Translation::Opcode>(it.Next()); |
1027 DCHECK_EQ(Translation::BEGIN, frame_opcode); | 1042 DCHECK_EQ(Translation::BEGIN, frame_opcode); |
1028 it.Next(); // Drop frame count. | 1043 it.Next(); // Drop frame count. |
1029 int jsframe_count = it.Next(); | 1044 int jsframe_count = it.Next(); |
1030 | 1045 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1133 // code object. | 1148 // code object. |
1134 if (!code->contains(pc())) { | 1149 if (!code->contains(pc())) { |
1135 code = isolate()->inner_pointer_to_code_cache()-> | 1150 code = isolate()->inner_pointer_to_code_cache()-> |
1136 GcSafeFindCodeForInnerPointer(pc()); | 1151 GcSafeFindCodeForInnerPointer(pc()); |
1137 } | 1152 } |
1138 DCHECK(code != NULL); | 1153 DCHECK(code != NULL); |
1139 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 1154 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
1140 | 1155 |
1141 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); | 1156 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); |
1142 *deopt_index = safepoint_entry.deoptimization_index(); | 1157 *deopt_index = safepoint_entry.deoptimization_index(); |
1143 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex); | 1158 if (*deopt_index != Safepoint::kNoDeoptimizationIndex) { |
1144 | 1159 return DeoptimizationInputData::cast(code->deoptimization_data()); |
1145 return DeoptimizationInputData::cast(code->deoptimization_data()); | 1160 } |
| 1161 return nullptr; |
1146 } | 1162 } |
1147 | 1163 |
1148 | 1164 |
1149 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const { | 1165 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const { |
1150 DCHECK(functions->length() == 0); | 1166 DCHECK(functions->length() == 0); |
1151 DCHECK(is_optimized()); | 1167 DCHECK(is_optimized()); |
1152 | 1168 |
1153 // Delegate to JS frame in absence of turbofan deoptimization. | 1169 // Delegate to JS frame in absence of turbofan deoptimization. |
1154 // TODO(turbofan): Revisit once we support deoptimization across the board. | 1170 // TODO(turbofan): Revisit once we support deoptimization across the board. |
1155 Code* code = LookupCode(); | 1171 Code* code = LookupCode(); |
1156 if (code->kind() == Code::BUILTIN || | 1172 if (code->kind() == Code::BUILTIN || |
1157 CannotDeoptFromAsmCode(code, function())) { | 1173 CannotDeoptFromAsmCode(code, function())) { |
1158 return JavaScriptFrame::GetFunctions(functions); | 1174 return JavaScriptFrame::GetFunctions(functions); |
1159 } | 1175 } |
1160 | 1176 |
1161 DisallowHeapAllocation no_gc; | 1177 DisallowHeapAllocation no_gc; |
1162 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 1178 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
1163 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index); | 1179 DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index); |
| 1180 DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex); |
1164 FixedArray* const literal_array = data->LiteralArray(); | 1181 FixedArray* const literal_array = data->LiteralArray(); |
1165 | 1182 |
1166 TranslationIterator it(data->TranslationByteArray(), | 1183 TranslationIterator it(data->TranslationByteArray(), |
1167 data->TranslationIndex(deopt_index)->value()); | 1184 data->TranslationIndex(deopt_index)->value()); |
1168 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 1185 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
1169 DCHECK_EQ(Translation::BEGIN, opcode); | 1186 DCHECK_EQ(Translation::BEGIN, opcode); |
1170 it.Next(); // Skip frame count. | 1187 it.Next(); // Skip frame count. |
1171 int jsframe_count = it.Next(); | 1188 int jsframe_count = it.Next(); |
1172 | 1189 |
1173 // We insert the frames in reverse order because the frames | 1190 // We insert the frames in reverse order because the frames |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1260 | 1277 |
1261 void InterpretedFrame::WriteInterpreterRegister(int register_index, | 1278 void InterpretedFrame::WriteInterpreterRegister(int register_index, |
1262 Object* value) { | 1279 Object* value) { |
1263 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex; | 1280 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex; |
1264 DCHECK_EQ( | 1281 DCHECK_EQ( |
1265 InterpreterFrameConstants::kRegisterFileFromFp, | 1282 InterpreterFrameConstants::kRegisterFileFromFp, |
1266 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); | 1283 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); |
1267 return SetExpression(index + register_index, value); | 1284 return SetExpression(index + register_index, value); |
1268 } | 1285 } |
1269 | 1286 |
1270 void InterpretedFrame::Summarize(List<FrameSummary>* functions) const { | 1287 void InterpretedFrame::Summarize(List<FrameSummary>* functions, |
| 1288 FrameSummary::Mode mode) const { |
1271 DCHECK(functions->length() == 0); | 1289 DCHECK(functions->length() == 0); |
1272 AbstractCode* abstract_code = | 1290 AbstractCode* abstract_code = |
1273 AbstractCode::cast(function()->shared()->bytecode_array()); | 1291 AbstractCode::cast(function()->shared()->bytecode_array()); |
1274 FrameSummary summary(receiver(), function(), abstract_code, | 1292 FrameSummary summary(receiver(), function(), abstract_code, |
1275 GetBytecodeOffset(), IsConstructor()); | 1293 GetBytecodeOffset(), IsConstructor()); |
1276 functions->Add(summary); | 1294 functions->Add(summary); |
1277 } | 1295 } |
1278 | 1296 |
1279 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { | 1297 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { |
1280 return Smi::cast(GetExpression(0))->value(); | 1298 return Smi::cast(GetExpression(0))->value(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 | 1344 |
1327 JSFunction* WasmFrame::function() const { | 1345 JSFunction* WasmFrame::function() const { |
1328 // TODO(clemensh): generate the right JSFunctions once per wasm function and | 1346 // TODO(clemensh): generate the right JSFunctions once per wasm function and |
1329 // cache them | 1347 // cache them |
1330 Factory* factory = isolate()->factory(); | 1348 Factory* factory = isolate()->factory(); |
1331 Handle<JSFunction> fun = | 1349 Handle<JSFunction> fun = |
1332 factory->NewFunction(factory->NewStringFromAsciiChecked("<WASM>")); | 1350 factory->NewFunction(factory->NewStringFromAsciiChecked("<WASM>")); |
1333 return *fun; | 1351 return *fun; |
1334 } | 1352 } |
1335 | 1353 |
1336 void WasmFrame::Summarize(List<FrameSummary>* functions) const { | 1354 void WasmFrame::Summarize(List<FrameSummary>* functions, |
| 1355 FrameSummary::Mode mode) const { |
1337 DCHECK(functions->length() == 0); | 1356 DCHECK(functions->length() == 0); |
1338 Code* code = LookupCode(); | 1357 Code* code = LookupCode(); |
1339 int offset = static_cast<int>(pc() - code->instruction_start()); | 1358 int offset = static_cast<int>(pc() - code->instruction_start()); |
1340 AbstractCode* abstract_code = AbstractCode::cast(code); | 1359 AbstractCode* abstract_code = AbstractCode::cast(code); |
1341 Handle<JSFunction> fun(function(), isolate()); | 1360 Handle<JSFunction> fun(function(), isolate()); |
1342 FrameSummary summary(receiver(), *fun, abstract_code, offset, false); | 1361 FrameSummary summary(receiver(), *fun, abstract_code, offset, false); |
1343 functions->Add(summary); | 1362 functions->Add(summary); |
1344 } | 1363 } |
1345 | 1364 |
1346 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } | 1365 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1779 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1798 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1780 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1799 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1781 list.Add(frame, zone); | 1800 list.Add(frame, zone); |
1782 } | 1801 } |
1783 return list.ToVector(); | 1802 return list.ToVector(); |
1784 } | 1803 } |
1785 | 1804 |
1786 | 1805 |
1787 } // namespace internal | 1806 } // namespace internal |
1788 } // namespace v8 | 1807 } // namespace v8 |
OLD | NEW |