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 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 Address StandardFrame::GetExpressionAddress(int n) const { | 635 Address StandardFrame::GetExpressionAddress(int n) const { |
629 const int offset = StandardFrameConstants::kExpressionsOffset; | 636 const int offset = StandardFrameConstants::kExpressionsOffset; |
630 return fp() + offset - n * kPointerSize; | 637 return fp() + offset - n * kPointerSize; |
631 } | 638 } |
632 | 639 |
633 Address InterpretedFrame::GetExpressionAddress(int n) const { | 640 Address InterpretedFrame::GetExpressionAddress(int n) const { |
634 const int offset = InterpreterFrameConstants::kExpressionsOffset; | 641 const int offset = InterpreterFrameConstants::kExpressionsOffset; |
635 return fp() + offset - n * kPointerSize; | 642 return fp() + offset - n * kPointerSize; |
636 } | 643 } |
637 | 644 |
| 645 Script* StandardFrame::script() const { |
| 646 // This should only be called on frames which override this method. |
| 647 DCHECK(false); |
| 648 return nullptr; |
| 649 } |
| 650 |
| 651 Object* StandardFrame::receiver() const { |
| 652 return isolate()->heap()->undefined_value(); |
| 653 } |
| 654 |
| 655 Object* StandardFrame::context() const { |
| 656 return isolate()->heap()->undefined_value(); |
| 657 } |
| 658 |
638 int StandardFrame::ComputeExpressionsCount() const { | 659 int StandardFrame::ComputeExpressionsCount() const { |
639 Address base = GetExpressionAddress(0); | 660 Address base = GetExpressionAddress(0); |
640 Address limit = sp() - kPointerSize; | 661 Address limit = sp() - kPointerSize; |
641 DCHECK(base >= limit); // stack grows downwards | 662 DCHECK(base >= limit); // stack grows downwards |
642 // Include register-allocated locals in number of expressions. | 663 // Include register-allocated locals in number of expressions. |
643 return static_cast<int>((base - limit) / kPointerSize); | 664 return static_cast<int>((base - limit) / kPointerSize); |
644 } | 665 } |
645 | 666 |
| 667 Object* StandardFrame::GetParameter(int index) const { |
| 668 // StandardFrame does not define any parameters. |
| 669 UNREACHABLE(); |
| 670 return nullptr; |
| 671 } |
| 672 |
| 673 int StandardFrame::ComputeParametersCount() const { return 0; } |
646 | 674 |
647 void StandardFrame::ComputeCallerState(State* state) const { | 675 void StandardFrame::ComputeCallerState(State* state) const { |
648 state->sp = caller_sp(); | 676 state->sp = caller_sp(); |
649 state->fp = caller_fp(); | 677 state->fp = caller_fp(); |
650 state->pc_address = ResolveReturnAddressLocation( | 678 state->pc_address = ResolveReturnAddressLocation( |
651 reinterpret_cast<Address*>(ComputePCAddress(fp()))); | 679 reinterpret_cast<Address*>(ComputePCAddress(fp()))); |
652 state->constant_pool_address = | 680 state->constant_pool_address = |
653 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); | 681 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); |
654 } | 682 } |
655 | 683 |
656 | 684 |
657 void StandardFrame::SetCallerFp(Address caller_fp) { | 685 void StandardFrame::SetCallerFp(Address caller_fp) { |
658 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = | 686 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = |
659 caller_fp; | 687 caller_fp; |
660 } | 688 } |
661 | 689 |
| 690 bool StandardFrame::IsConstructor() const { return false; } |
662 | 691 |
663 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 692 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
664 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 693 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
665 // possibly find pointers in optimized frames in that state. | 694 // possibly find pointers in optimized frames in that state. |
666 DCHECK(can_access_heap_objects()); | 695 DCHECK(can_access_heap_objects()); |
667 | 696 |
668 // Compute the safepoint information. | 697 // Compute the safepoint information. |
669 unsigned stack_slots = 0; | 698 unsigned stack_slots = 0; |
670 SafepointEntry safepoint_entry; | 699 SafepointEntry safepoint_entry; |
671 Code* code = StackFrame::GetSafepointData( | 700 Code* code = StackFrame::GetSafepointData( |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 IsConstructor(), mode); | 895 IsConstructor(), mode); |
867 functions->Add(summary); | 896 functions->Add(summary); |
868 } | 897 } |
869 | 898 |
870 JSFunction* JavaScriptFrame::function() const { | 899 JSFunction* JavaScriptFrame::function() const { |
871 return JSFunction::cast(function_slot_object()); | 900 return JSFunction::cast(function_slot_object()); |
872 } | 901 } |
873 | 902 |
874 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } | 903 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } |
875 | 904 |
| 905 Script* JavaScriptFrame::script() const { |
| 906 return Script::cast(function()->shared()->script()); |
| 907 } |
| 908 |
| 909 Object* JavaScriptFrame::context() const { |
| 910 const int offset = StandardFrameConstants::kContextOffset; |
| 911 Object* maybe_result = Memory::Object_at(fp() + offset); |
| 912 DCHECK(!maybe_result->IsSmi()); |
| 913 return maybe_result; |
| 914 } |
| 915 |
876 int JavaScriptFrame::LookupExceptionHandlerInTable( | 916 int JavaScriptFrame::LookupExceptionHandlerInTable( |
877 int* stack_depth, HandlerTable::CatchPrediction* prediction) { | 917 int* stack_depth, HandlerTable::CatchPrediction* prediction) { |
878 Code* code = LookupCode(); | 918 Code* code = LookupCode(); |
879 DCHECK(!code->is_optimized_code()); | 919 DCHECK(!code->is_optimized_code()); |
880 HandlerTable* table = HandlerTable::cast(code->handler_table()); | 920 HandlerTable* table = HandlerTable::cast(code->handler_table()); |
881 int pc_offset = static_cast<int>(pc() - code->entry()); | 921 int pc_offset = static_cast<int>(pc() - code->entry()); |
882 return table->LookupRange(pc_offset, stack_depth, prediction); | 922 return table->LookupRange(pc_offset, stack_depth, prediction); |
883 } | 923 } |
884 | 924 |
885 | 925 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 | 985 |
946 | 986 |
947 void JavaScriptFrame::SaveOperandStack(FixedArray* store) const { | 987 void JavaScriptFrame::SaveOperandStack(FixedArray* store) const { |
948 int operands_count = store->length(); | 988 int operands_count = store->length(); |
949 DCHECK_LE(operands_count, ComputeOperandsCount()); | 989 DCHECK_LE(operands_count, ComputeOperandsCount()); |
950 for (int i = 0; i < operands_count; i++) { | 990 for (int i = 0; i < operands_count; i++) { |
951 store->set(i, GetOperand(i)); | 991 store->set(i, GetOperand(i)); |
952 } | 992 } |
953 } | 993 } |
954 | 994 |
| 995 Object* JavaScriptFrame::GetParameter(int index) const { |
| 996 return Memory::Object_at(GetParameterSlot(index)); |
| 997 } |
| 998 |
| 999 int JavaScriptFrame::ComputeParametersCount() const { |
| 1000 return GetNumberOfIncomingArguments(); |
| 1001 } |
| 1002 |
955 namespace { | 1003 namespace { |
956 | 1004 |
957 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) { | 1005 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) { |
958 return code->is_turbofanned() && function->shared()->asm_function() && | 1006 return code->is_turbofanned() && function->shared()->asm_function() && |
959 !FLAG_turbo_asm_deoptimization; | 1007 !FLAG_turbo_asm_deoptimization; |
960 } | 1008 } |
961 | 1009 |
962 } // namespace | 1010 } // namespace |
963 | 1011 |
964 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, | 1012 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 Code* WasmFrame::unchecked_code() const { | 1389 Code* WasmFrame::unchecked_code() const { |
1342 return static_cast<Code*>(isolate()->FindCodeObject(pc())); | 1390 return static_cast<Code*>(isolate()->FindCodeObject(pc())); |
1343 } | 1391 } |
1344 | 1392 |
1345 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } | 1393 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } |
1346 | 1394 |
1347 Address WasmFrame::GetCallerStackPointer() const { | 1395 Address WasmFrame::GetCallerStackPointer() const { |
1348 return fp() + ExitFrameConstants::kCallerSPOffset; | 1396 return fp() + ExitFrameConstants::kCallerSPOffset; |
1349 } | 1397 } |
1350 | 1398 |
1351 Object* WasmFrame::wasm_obj() { | 1399 Object* WasmFrame::wasm_obj() const { |
1352 FixedArray* deopt_data = LookupCode()->deoptimization_data(); | 1400 FixedArray* deopt_data = LookupCode()->deoptimization_data(); |
1353 DCHECK(deopt_data->length() == 2); | 1401 DCHECK(deopt_data->length() == 2); |
1354 return deopt_data->get(0); | 1402 return deopt_data->get(0); |
1355 } | 1403 } |
1356 | 1404 |
1357 uint32_t WasmFrame::function_index() { | 1405 uint32_t WasmFrame::function_index() const { |
1358 FixedArray* deopt_data = LookupCode()->deoptimization_data(); | 1406 FixedArray* deopt_data = LookupCode()->deoptimization_data(); |
1359 DCHECK(deopt_data->length() == 2); | 1407 DCHECK(deopt_data->length() == 2); |
1360 Object* func_index_obj = deopt_data->get(1); | 1408 return Smi::cast(deopt_data->get(1))->value(); |
1361 if (func_index_obj->IsUndefined(isolate())) return static_cast<uint32_t>(-1); | 1409 } |
1362 if (func_index_obj->IsSmi()) return Smi::cast(func_index_obj)->value(); | 1410 |
1363 DCHECK(func_index_obj->IsHeapNumber()); | 1411 Script* WasmFrame::script() const { |
1364 uint32_t val = static_cast<uint32_t>(-1); | 1412 JSObject* wasm = JSObject::cast(wasm_obj()); |
1365 func_index_obj->ToUint32(&val); | 1413 Handle<wasm::WasmDebugInfo> debug_info(wasm::GetDebugInfo(wasm), isolate()); |
1366 DCHECK(val != static_cast<uint32_t>(-1)); | 1414 return wasm::WasmDebugInfo::GetFunctionScript(debug_info, function_index()); |
1367 return val; | |
1368 } | 1415 } |
1369 | 1416 |
1370 namespace { | 1417 namespace { |
1371 | 1418 |
1372 | 1419 |
1373 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, | 1420 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, |
1374 Code* code) { | 1421 Code* code) { |
1375 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { | 1422 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { |
1376 std::ostringstream os; | 1423 std::ostringstream os; |
1377 os << "--------- s o u r c e c o d e ---------\n" | 1424 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... |
1797 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1844 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1798 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1845 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1799 list.Add(frame, zone); | 1846 list.Add(frame, zone); |
1800 } | 1847 } |
1801 return list.ToVector(); | 1848 return list.ToVector(); |
1802 } | 1849 } |
1803 | 1850 |
1804 | 1851 |
1805 } // namespace internal | 1852 } // namespace internal |
1806 } // namespace v8 | 1853 } // namespace v8 |
OLD | NEW |