| 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" |
| 11 #include "src/base/bits.h" | 11 #include "src/base/bits.h" |
| 12 #include "src/deoptimizer.h" | 12 #include "src/deoptimizer.h" |
| 13 #include "src/frames-inl.h" | 13 #include "src/frames-inl.h" |
| 14 #include "src/full-codegen/full-codegen.h" | 14 #include "src/full-codegen/full-codegen.h" |
| 15 #include "src/register-configuration.h" | 15 #include "src/register-configuration.h" |
| 16 #include "src/safepoint-table.h" | 16 #include "src/safepoint-table.h" |
| 17 #include "src/string-stream.h" | 17 #include "src/string-stream.h" |
| 18 #include "src/vm-state-inl.h" | 18 #include "src/vm-state-inl.h" |
| 19 #include "src/wasm/wasm-debug.h" |
| 20 #include "src/wasm/wasm-module.h" |
| 19 | 21 |
| 20 namespace v8 { | 22 namespace v8 { |
| 21 namespace internal { | 23 namespace internal { |
| 22 | 24 |
| 23 ReturnAddressLocationResolver | 25 ReturnAddressLocationResolver |
| 24 StackFrame::return_address_location_resolver_ = NULL; | 26 StackFrame::return_address_location_resolver_ = NULL; |
| 25 | 27 |
| 26 | 28 |
| 27 // Iterator that supports traversing the stack handlers of a | 29 // Iterator that supports traversing the stack handlers of a |
| 28 // particular frame. Needs to know the top of the handler chain. | 30 // particular frame. Needs to know the top of the handler chain. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 56 #define INITIALIZE_SINGLETON(type, field) field##_(this), | 58 #define INITIALIZE_SINGLETON(type, field) field##_(this), |
| 57 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate, | 59 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate, |
| 58 bool can_access_heap_objects) | 60 bool can_access_heap_objects) |
| 59 : isolate_(isolate), | 61 : isolate_(isolate), |
| 60 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 62 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 61 frame_(NULL), handler_(NULL), | 63 frame_(NULL), handler_(NULL), |
| 62 can_access_heap_objects_(can_access_heap_objects) { | 64 can_access_heap_objects_(can_access_heap_objects) { |
| 63 } | 65 } |
| 64 #undef INITIALIZE_SINGLETON | 66 #undef INITIALIZE_SINGLETON |
| 65 | 67 |
| 66 | |
| 67 StackFrameIterator::StackFrameIterator(Isolate* isolate) | 68 StackFrameIterator::StackFrameIterator(Isolate* isolate) |
| 68 : StackFrameIteratorBase(isolate, true) { | 69 : StackFrameIterator(isolate, isolate->thread_local_top()) {} |
| 69 Reset(isolate->thread_local_top()); | |
| 70 } | |
| 71 | |
| 72 | 70 |
| 73 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) | 71 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) |
| 74 : StackFrameIteratorBase(isolate, true) { | 72 : StackFrameIteratorBase(isolate, true) { |
| 75 Reset(t); | 73 Reset(t); |
| 76 } | 74 } |
| 77 | 75 |
| 78 | |
| 79 void StackFrameIterator::Advance() { | 76 void StackFrameIterator::Advance() { |
| 80 DCHECK(!done()); | 77 DCHECK(!done()); |
| 81 // Compute the state of the calling frame before restoring | 78 // Compute the state of the calling frame before restoring |
| 82 // callee-saved registers and unwinding handlers. This allows the | 79 // callee-saved registers and unwinding handlers. This allows the |
| 83 // frame code that computes the caller state to access the top | 80 // frame code that computes the caller state to access the top |
| 84 // handler and the value of any callee-saved register if needed. | 81 // handler and the value of any callee-saved register if needed. |
| 85 StackFrame::State state; | 82 StackFrame::State state; |
| 86 StackFrame::Type type = frame_->GetCallerState(&state); | 83 StackFrame::Type type = frame_->GetCallerState(&state); |
| 87 | 84 |
| 88 // Unwind handlers corresponding to the current frame. | 85 // Unwind handlers corresponding to the current frame. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 } | 155 } |
| 159 | 156 |
| 160 | 157 |
| 161 // ------------------------------------------------------------------------- | 158 // ------------------------------------------------------------------------- |
| 162 | 159 |
| 163 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) | 160 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) |
| 164 : iterator_(isolate) { | 161 : iterator_(isolate) { |
| 165 if (!done() && !IsValidFrame(iterator_.frame())) Advance(); | 162 if (!done() && !IsValidFrame(iterator_.frame())) Advance(); |
| 166 } | 163 } |
| 167 | 164 |
| 165 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate, |
| 166 StackFrame::Id id) |
| 167 : StackTraceFrameIterator(isolate) { |
| 168 while (!done() && frame()->id() != id) Advance(); |
| 169 } |
| 168 | 170 |
| 169 void StackTraceFrameIterator::Advance() { | 171 void StackTraceFrameIterator::Advance() { |
| 170 do { | 172 do { |
| 171 iterator_.Advance(); | 173 iterator_.Advance(); |
| 172 } while (!done() && !IsValidFrame(iterator_.frame())); | 174 } while (!done() && !IsValidFrame(iterator_.frame())); |
| 173 } | 175 } |
| 174 | 176 |
| 175 bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const { | 177 bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const { |
| 176 if (frame->is_java_script()) { | 178 if (frame->is_java_script()) { |
| 177 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame); | 179 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame); |
| 178 if (!jsFrame->function()->IsJSFunction()) return false; | 180 if (!jsFrame->function()->IsJSFunction()) return false; |
| 179 Object* script = jsFrame->function()->shared()->script(); | 181 Object* script = jsFrame->function()->shared()->script(); |
| 180 // Don't show functions from native scripts to user. | 182 // Don't show functions from native scripts to user. |
| 181 return (script->IsScript() && | 183 return (script->IsScript() && |
| 182 Script::TYPE_NATIVE != Script::cast(script)->type()); | 184 Script::TYPE_NATIVE != Script::cast(script)->type()); |
| 183 } | 185 } |
| 184 // apart from javascript, only wasm is valid | 186 // apart from javascript, only wasm is valid |
| 185 return frame->is_wasm(); | 187 return frame->is_wasm(); |
| 186 } | 188 } |
| 187 | 189 |
| 190 void StackTraceFrameIterator::AdvanceToArgumentsFrame() { |
| 191 if (!is_javascript() || !javascript_frame()->has_adapted_arguments()) return; |
| 192 iterator_.Advance(); |
| 193 DCHECK(iterator_.frame()->is_arguments_adaptor()); |
| 194 } |
| 188 | 195 |
| 189 // ------------------------------------------------------------------------- | 196 // ------------------------------------------------------------------------- |
| 190 | 197 |
| 191 | 198 |
| 192 SafeStackFrameIterator::SafeStackFrameIterator( | 199 SafeStackFrameIterator::SafeStackFrameIterator( |
| 193 Isolate* isolate, | 200 Isolate* isolate, |
| 194 Address fp, Address sp, Address js_entry_sp) | 201 Address fp, Address sp, Address js_entry_sp) |
| 195 : StackFrameIteratorBase(isolate, false), | 202 : StackFrameIteratorBase(isolate, false), |
| 196 low_bound_(sp), | 203 low_bound_(sp), |
| 197 high_bound_(js_entry_sp), | 204 high_bound_(js_entry_sp), |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 Address StandardFrame::GetExpressionAddress(int n) const { | 631 Address StandardFrame::GetExpressionAddress(int n) const { |
| 625 const int offset = StandardFrameConstants::kExpressionsOffset; | 632 const int offset = StandardFrameConstants::kExpressionsOffset; |
| 626 return fp() + offset - n * kPointerSize; | 633 return fp() + offset - n * kPointerSize; |
| 627 } | 634 } |
| 628 | 635 |
| 629 Address InterpretedFrame::GetExpressionAddress(int n) const { | 636 Address InterpretedFrame::GetExpressionAddress(int n) const { |
| 630 const int offset = InterpreterFrameConstants::kExpressionsOffset; | 637 const int offset = InterpreterFrameConstants::kExpressionsOffset; |
| 631 return fp() + offset - n * kPointerSize; | 638 return fp() + offset - n * kPointerSize; |
| 632 } | 639 } |
| 633 | 640 |
| 641 Script* StandardFrame::script() const { |
| 642 // This should only be called on frames which override this method. |
| 643 DCHECK(false); |
| 644 return nullptr; |
| 645 } |
| 646 |
| 647 Object* StandardFrame::context() const { |
| 648 return isolate()->heap()->undefined_value(); |
| 649 } |
| 650 |
| 634 int StandardFrame::ComputeExpressionsCount() const { | 651 int StandardFrame::ComputeExpressionsCount() const { |
| 635 Address base = GetExpressionAddress(0); | 652 Address base = GetExpressionAddress(0); |
| 636 Address limit = sp() - kPointerSize; | 653 Address limit = sp() - kPointerSize; |
| 637 DCHECK(base >= limit); // stack grows downwards | 654 DCHECK(base >= limit); // stack grows downwards |
| 638 // Include register-allocated locals in number of expressions. | 655 // Include register-allocated locals in number of expressions. |
| 639 return static_cast<int>((base - limit) / kPointerSize); | 656 return static_cast<int>((base - limit) / kPointerSize); |
| 640 } | 657 } |
| 641 | 658 |
| 659 Object* StandardFrame::GetParameter(int index) const { |
| 660 // StandardFrame does not define any parameters. |
| 661 UNREACHABLE(); |
| 662 return nullptr; |
| 663 } |
| 664 |
| 665 int StandardFrame::ComputeParametersCount() const { return 0; } |
| 642 | 666 |
| 643 void StandardFrame::ComputeCallerState(State* state) const { | 667 void StandardFrame::ComputeCallerState(State* state) const { |
| 644 state->sp = caller_sp(); | 668 state->sp = caller_sp(); |
| 645 state->fp = caller_fp(); | 669 state->fp = caller_fp(); |
| 646 state->pc_address = ResolveReturnAddressLocation( | 670 state->pc_address = ResolveReturnAddressLocation( |
| 647 reinterpret_cast<Address*>(ComputePCAddress(fp()))); | 671 reinterpret_cast<Address*>(ComputePCAddress(fp()))); |
| 648 state->constant_pool_address = | 672 state->constant_pool_address = |
| 649 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); | 673 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); |
| 650 } | 674 } |
| 651 | 675 |
| 652 | 676 |
| 653 void StandardFrame::SetCallerFp(Address caller_fp) { | 677 void StandardFrame::SetCallerFp(Address caller_fp) { |
| 654 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = | 678 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = |
| 655 caller_fp; | 679 caller_fp; |
| 656 } | 680 } |
| 657 | 681 |
| 682 bool StandardFrame::IsConstructor() const { return false; } |
| 658 | 683 |
| 659 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 684 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
| 660 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 685 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
| 661 // possibly find pointers in optimized frames in that state. | 686 // possibly find pointers in optimized frames in that state. |
| 662 DCHECK(can_access_heap_objects()); | 687 DCHECK(can_access_heap_objects()); |
| 663 | 688 |
| 664 // Compute the safepoint information. | 689 // Compute the safepoint information. |
| 665 unsigned stack_slots = 0; | 690 unsigned stack_slots = 0; |
| 666 SafepointEntry safepoint_entry; | 691 SafepointEntry safepoint_entry; |
| 667 Code* code = StackFrame::GetSafepointData( | 692 Code* code = StackFrame::GetSafepointData( |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 IsConstructor(), mode); | 886 IsConstructor(), mode); |
| 862 functions->Add(summary); | 887 functions->Add(summary); |
| 863 } | 888 } |
| 864 | 889 |
| 865 JSFunction* JavaScriptFrame::function() const { | 890 JSFunction* JavaScriptFrame::function() const { |
| 866 return JSFunction::cast(function_slot_object()); | 891 return JSFunction::cast(function_slot_object()); |
| 867 } | 892 } |
| 868 | 893 |
| 869 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } | 894 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } |
| 870 | 895 |
| 896 Script* JavaScriptFrame::script() const { |
| 897 return Script::cast(function()->shared()->script()); |
| 898 } |
| 899 |
| 900 Object* JavaScriptFrame::context() const { |
| 901 const int offset = StandardFrameConstants::kContextOffset; |
| 902 Object* maybe_result = Memory::Object_at(fp() + offset); |
| 903 DCHECK(!maybe_result->IsSmi()); |
| 904 return maybe_result; |
| 905 } |
| 906 |
| 871 int JavaScriptFrame::LookupExceptionHandlerInTable( | 907 int JavaScriptFrame::LookupExceptionHandlerInTable( |
| 872 int* stack_depth, HandlerTable::CatchPrediction* prediction) { | 908 int* stack_depth, HandlerTable::CatchPrediction* prediction) { |
| 873 Code* code = LookupCode(); | 909 Code* code = LookupCode(); |
| 874 DCHECK(!code->is_optimized_code()); | 910 DCHECK(!code->is_optimized_code()); |
| 875 HandlerTable* table = HandlerTable::cast(code->handler_table()); | 911 HandlerTable* table = HandlerTable::cast(code->handler_table()); |
| 876 int pc_offset = static_cast<int>(pc() - code->entry()); | 912 int pc_offset = static_cast<int>(pc() - code->entry()); |
| 877 return table->LookupRange(pc_offset, stack_depth, prediction); | 913 return table->LookupRange(pc_offset, stack_depth, prediction); |
| 878 } | 914 } |
| 879 | 915 |
| 880 | 916 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 | 976 |
| 941 | 977 |
| 942 void JavaScriptFrame::SaveOperandStack(FixedArray* store) const { | 978 void JavaScriptFrame::SaveOperandStack(FixedArray* store) const { |
| 943 int operands_count = store->length(); | 979 int operands_count = store->length(); |
| 944 DCHECK_LE(operands_count, ComputeOperandsCount()); | 980 DCHECK_LE(operands_count, ComputeOperandsCount()); |
| 945 for (int i = 0; i < operands_count; i++) { | 981 for (int i = 0; i < operands_count; i++) { |
| 946 store->set(i, GetOperand(i)); | 982 store->set(i, GetOperand(i)); |
| 947 } | 983 } |
| 948 } | 984 } |
| 949 | 985 |
| 986 Object* JavaScriptFrame::GetParameter(int index) const { |
| 987 return Memory::Object_at(GetParameterSlot(index)); |
| 988 } |
| 989 |
| 990 int JavaScriptFrame::ComputeParametersCount() const { |
| 991 return GetNumberOfIncomingArguments(); |
| 992 } |
| 993 |
| 950 namespace { | 994 namespace { |
| 951 | 995 |
| 952 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) { | 996 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) { |
| 953 return code->is_turbofanned() && function->shared()->asm_function() && | 997 return code->is_turbofanned() && function->shared()->asm_function() && |
| 954 !FLAG_turbo_asm_deoptimization; | 998 !FLAG_turbo_asm_deoptimization; |
| 955 } | 999 } |
| 956 | 1000 |
| 957 } // namespace | 1001 } // namespace |
| 958 | 1002 |
| 959 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, | 1003 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1332 Code* WasmFrame::unchecked_code() const { | 1376 Code* WasmFrame::unchecked_code() const { |
| 1333 return static_cast<Code*>(isolate()->FindCodeObject(pc())); | 1377 return static_cast<Code*>(isolate()->FindCodeObject(pc())); |
| 1334 } | 1378 } |
| 1335 | 1379 |
| 1336 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } | 1380 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } |
| 1337 | 1381 |
| 1338 Address WasmFrame::GetCallerStackPointer() const { | 1382 Address WasmFrame::GetCallerStackPointer() const { |
| 1339 return fp() + ExitFrameConstants::kCallerSPOffset; | 1383 return fp() + ExitFrameConstants::kCallerSPOffset; |
| 1340 } | 1384 } |
| 1341 | 1385 |
| 1342 Object* WasmFrame::wasm_obj() { | 1386 Object* WasmFrame::wasm_obj() const { |
| 1343 FixedArray* deopt_data = LookupCode()->deoptimization_data(); | 1387 FixedArray* deopt_data = LookupCode()->deoptimization_data(); |
| 1344 DCHECK(deopt_data->length() == 2); | 1388 DCHECK(deopt_data->length() == 2); |
| 1345 return deopt_data->get(0); | 1389 return deopt_data->get(0); |
| 1346 } | 1390 } |
| 1347 | 1391 |
| 1348 uint32_t WasmFrame::function_index() { | 1392 uint32_t WasmFrame::function_index() const { |
| 1349 FixedArray* deopt_data = LookupCode()->deoptimization_data(); | 1393 FixedArray* deopt_data = LookupCode()->deoptimization_data(); |
| 1350 DCHECK(deopt_data->length() == 2); | 1394 DCHECK(deopt_data->length() == 2); |
| 1351 Object* func_index_obj = deopt_data->get(1); | 1395 return Smi::cast(deopt_data->get(1))->value(); |
| 1352 if (func_index_obj->IsUndefined(isolate())) return static_cast<uint32_t>(-1); | 1396 } |
| 1353 if (func_index_obj->IsSmi()) return Smi::cast(func_index_obj)->value(); | 1397 |
| 1354 DCHECK(func_index_obj->IsHeapNumber()); | 1398 Script* WasmFrame::script() const { |
| 1355 uint32_t val = static_cast<uint32_t>(-1); | 1399 JSObject* wasm = JSObject::cast(wasm_obj()); |
| 1356 func_index_obj->ToUint32(&val); | 1400 int func_index = function_index(); |
| 1357 DCHECK(val != static_cast<uint32_t>(-1)); | 1401 return wasm::GetDebugInfo(wasm)->GetFunctionScript(func_index); |
| 1358 return val; | |
| 1359 } | 1402 } |
| 1360 | 1403 |
| 1361 namespace { | 1404 namespace { |
| 1362 | 1405 |
| 1363 | 1406 |
| 1364 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, | 1407 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, |
| 1365 Code* code) { | 1408 Code* code) { |
| 1366 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { | 1409 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { |
| 1367 std::ostringstream os; | 1410 std::ostringstream os; |
| 1368 os << "--------- s o u r c e c o d e ---------\n" | 1411 os << "--------- s o u r c e c o d e ---------\n" |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1831 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1789 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1832 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
| 1790 list.Add(frame, zone); | 1833 list.Add(frame, zone); |
| 1791 } | 1834 } |
| 1792 return list.ToVector(); | 1835 return list.ToVector(); |
| 1793 } | 1836 } |
| 1794 | 1837 |
| 1795 | 1838 |
| 1796 } // namespace internal | 1839 } // namespace internal |
| 1797 } // namespace v8 | 1840 } // namespace v8 |
| OLD | NEW |