| 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 |