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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 | 174 |
175 bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const { | 175 bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const { |
176 if (frame->is_java_script()) { | 176 if (frame->is_java_script()) { |
177 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame); | 177 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame); |
178 if (!jsFrame->function()->IsJSFunction()) return false; | 178 if (!jsFrame->function()->IsJSFunction()) return false; |
179 Object* script = jsFrame->function()->shared()->script(); | 179 Object* script = jsFrame->function()->shared()->script(); |
180 // Don't show functions from native scripts to user. | 180 // Don't show functions from native scripts to user. |
181 return (script->IsScript() && | 181 return (script->IsScript() && |
182 Script::TYPE_NATIVE != Script::cast(script)->type()); | 182 Script::TYPE_NATIVE != Script::cast(script)->type()); |
183 } | 183 } |
184 // apart from javascript, only wasm is valid | 184 // apart from javascript, only wasm and builtin_exit are valid |
185 return frame->is_wasm(); | 185 return frame->is_wasm() || frame->is_builtin_exit(); |
186 } | 186 } |
187 | 187 |
188 | 188 |
189 // ------------------------------------------------------------------------- | 189 // ------------------------------------------------------------------------- |
190 | 190 |
191 | 191 |
192 SafeStackFrameIterator::SafeStackFrameIterator( | 192 SafeStackFrameIterator::SafeStackFrameIterator( |
193 Isolate* isolate, | 193 Isolate* isolate, |
194 Address fp, Address sp, Address js_entry_sp) | 194 Address fp, Address sp, Address js_entry_sp) |
195 : StackFrameIteratorBase(isolate, false), | 195 : StackFrameIteratorBase(isolate, false), |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 external_callback_scope_->scope_address() < frame_->fp()) { | 317 external_callback_scope_->scope_address() < frame_->fp()) { |
318 // As long as the setup of a frame is not atomic, we may happen to be | 318 // As long as the setup of a frame is not atomic, we may happen to be |
319 // in an interval where an ExternalCallbackScope is already created, | 319 // in an interval where an ExternalCallbackScope is already created, |
320 // but the frame is not yet entered. So we are actually observing | 320 // but the frame is not yet entered. So we are actually observing |
321 // the previous frame. | 321 // the previous frame. |
322 // Skip all the ExternalCallbackScope's that are below the current fp. | 322 // Skip all the ExternalCallbackScope's that are below the current fp. |
323 last_callback_scope = external_callback_scope_; | 323 last_callback_scope = external_callback_scope_; |
324 external_callback_scope_ = external_callback_scope_->previous(); | 324 external_callback_scope_ = external_callback_scope_->previous(); |
325 } | 325 } |
326 if (frame_->is_java_script()) break; | 326 if (frame_->is_java_script()) break; |
327 if (frame_->is_exit()) { | 327 if (frame_->is_exit() || frame_->is_builtin_exit()) { |
328 // Some of the EXIT frames may have ExternalCallbackScope allocated on | 328 // Some of the EXIT frames may have ExternalCallbackScope allocated on |
329 // top of them. In that case the scope corresponds to the first EXIT | 329 // top of them. In that case the scope corresponds to the first EXIT |
330 // frame beneath it. There may be other EXIT frames on top of the | 330 // frame beneath it. There may be other EXIT frames on top of the |
331 // ExternalCallbackScope, just skip them as we cannot collect any useful | 331 // ExternalCallbackScope, just skip them as we cannot collect any useful |
332 // information about them. | 332 // information about them. |
333 if (last_callback_scope) { | 333 if (last_callback_scope) { |
334 frame_->state_.pc_address = | 334 frame_->state_.pc_address = |
335 last_callback_scope->callback_entrypoint_address(); | 335 last_callback_scope->callback_entrypoint_address(); |
336 } | 336 } |
337 break; | 337 break; |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 } | 481 } |
482 } | 482 } |
483 | 483 |
484 DCHECK(marker->IsSmi()); | 484 DCHECK(marker->IsSmi()); |
485 StackFrame::Type candidate = | 485 StackFrame::Type candidate = |
486 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | 486 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
487 switch (candidate) { | 487 switch (candidate) { |
488 case ENTRY: | 488 case ENTRY: |
489 case ENTRY_CONSTRUCT: | 489 case ENTRY_CONSTRUCT: |
490 case EXIT: | 490 case EXIT: |
| 491 case BUILTIN_EXIT: |
491 case STUB: | 492 case STUB: |
492 case STUB_FAILURE_TRAMPOLINE: | 493 case STUB_FAILURE_TRAMPOLINE: |
493 case INTERNAL: | 494 case INTERNAL: |
494 case CONSTRUCT: | 495 case CONSTRUCT: |
495 case ARGUMENTS_ADAPTOR: | 496 case ARGUMENTS_ADAPTOR: |
496 case WASM_TO_JS: | 497 case WASM_TO_JS: |
497 case WASM: | 498 case WASM: |
498 return candidate; | 499 return candidate; |
499 case JS_TO_WASM: | 500 case JS_TO_WASM: |
500 case JAVA_SCRIPT: | 501 case JAVA_SCRIPT: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 Code* EntryConstructFrame::unchecked_code() const { | 555 Code* EntryConstructFrame::unchecked_code() const { |
555 return isolate()->heap()->js_construct_entry_code(); | 556 return isolate()->heap()->js_construct_entry_code(); |
556 } | 557 } |
557 | 558 |
558 | 559 |
559 Object*& ExitFrame::code_slot() const { | 560 Object*& ExitFrame::code_slot() const { |
560 const int offset = ExitFrameConstants::kCodeOffset; | 561 const int offset = ExitFrameConstants::kCodeOffset; |
561 return Memory::Object_at(fp() + offset); | 562 return Memory::Object_at(fp() + offset); |
562 } | 563 } |
563 | 564 |
564 | |
565 Code* ExitFrame::unchecked_code() const { | 565 Code* ExitFrame::unchecked_code() const { |
566 return reinterpret_cast<Code*>(code_slot()); | 566 return reinterpret_cast<Code*>(code_slot()); |
567 } | 567 } |
568 | 568 |
569 | 569 |
570 void ExitFrame::ComputeCallerState(State* state) const { | 570 void ExitFrame::ComputeCallerState(State* state) const { |
571 // Set up the caller state. | 571 // Set up the caller state. |
572 state->sp = caller_sp(); | 572 state->sp = caller_sp(); |
573 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); | 573 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); |
574 state->pc_address = ResolveReturnAddressLocation( | 574 state->pc_address = ResolveReturnAddressLocation( |
(...skipping 21 matching lines...) Expand all Loading... |
596 Address ExitFrame::GetCallerStackPointer() const { | 596 Address ExitFrame::GetCallerStackPointer() const { |
597 return fp() + ExitFrameConstants::kCallerSPOffset; | 597 return fp() + ExitFrameConstants::kCallerSPOffset; |
598 } | 598 } |
599 | 599 |
600 | 600 |
601 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { | 601 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { |
602 if (fp == 0) return NONE; | 602 if (fp == 0) return NONE; |
603 Address sp = ComputeStackPointer(fp); | 603 Address sp = ComputeStackPointer(fp); |
604 FillState(fp, sp, state); | 604 FillState(fp, sp, state); |
605 DCHECK(*state->pc_address != NULL); | 605 DCHECK(*state->pc_address != NULL); |
| 606 |
| 607 return ComputeFrameType(fp); |
| 608 } |
| 609 |
| 610 StackFrame::Type ExitFrame::ComputeFrameType(Address fp) { |
| 611 // Distinguish between between regular and builtin exit frames. |
| 612 // Default to EXIT in all hairy cases (e.g., when called from profiler). |
| 613 const int offset = CommonFrameConstants::kContextOrFrameTypeOffset; |
| 614 Object* marker = Memory::Object_at(fp + offset); |
| 615 |
| 616 if (!marker->IsSmi()) { |
| 617 return EXIT; |
| 618 } |
| 619 |
| 620 StackFrame::Type frame_type = |
| 621 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
| 622 if (frame_type == EXIT || frame_type == BUILTIN_EXIT) { |
| 623 return frame_type; |
| 624 } |
| 625 |
606 return EXIT; | 626 return EXIT; |
607 } | 627 } |
608 | 628 |
609 Address ExitFrame::ComputeStackPointer(Address fp) { | 629 Address ExitFrame::ComputeStackPointer(Address fp) { |
610 #if defined(USE_SIMULATOR) | 630 #if defined(USE_SIMULATOR) |
611 MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize); | 631 MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize); |
612 #endif | 632 #endif |
613 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); | 633 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); |
614 } | 634 } |
615 | 635 |
616 void ExitFrame::FillState(Address fp, Address sp, State* state) { | 636 void ExitFrame::FillState(Address fp, Address sp, State* state) { |
617 state->sp = sp; | 637 state->sp = sp; |
618 state->fp = fp; | 638 state->fp = fp; |
619 state->pc_address = ResolveReturnAddressLocation( | 639 state->pc_address = ResolveReturnAddressLocation( |
620 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); | 640 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); |
621 // The constant pool recorded in the exit frame is not associated | 641 // The constant pool recorded in the exit frame is not associated |
622 // with the pc in this state (the return address into a C entry | 642 // with the pc in this state (the return address into a C entry |
623 // stub). ComputeCallerState will retrieve the constant pool | 643 // stub). ComputeCallerState will retrieve the constant pool |
624 // together with the associated caller pc. | 644 // together with the associated caller pc. |
625 state->constant_pool_address = NULL; | 645 state->constant_pool_address = NULL; |
626 } | 646 } |
627 | 647 |
| 648 JSFunction* BuiltinExitFrame::function() const { |
| 649 return JSFunction::cast(function_slot_object()); |
| 650 } |
| 651 |
628 Address StandardFrame::GetExpressionAddress(int n) const { | 652 Address StandardFrame::GetExpressionAddress(int n) const { |
629 const int offset = StandardFrameConstants::kExpressionsOffset; | 653 const int offset = StandardFrameConstants::kExpressionsOffset; |
630 return fp() + offset - n * kPointerSize; | 654 return fp() + offset - n * kPointerSize; |
631 } | 655 } |
632 | 656 |
633 Address InterpretedFrame::GetExpressionAddress(int n) const { | 657 Address InterpretedFrame::GetExpressionAddress(int n) const { |
634 const int offset = InterpreterFrameConstants::kExpressionsOffset; | 658 const int offset = InterpreterFrameConstants::kExpressionsOffset; |
635 return fp() + offset - n * kPointerSize; | 659 return fp() + offset - n * kPointerSize; |
636 } | 660 } |
637 | 661 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp; | 700 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp; |
677 Object* marker = | 701 Object* marker = |
678 Memory::Object_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset); | 702 Memory::Object_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset); |
679 if (marker->IsSmi()) { | 703 if (marker->IsSmi()) { |
680 StackFrame::Type candidate = | 704 StackFrame::Type candidate = |
681 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | 705 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
682 switch (candidate) { | 706 switch (candidate) { |
683 case ENTRY: | 707 case ENTRY: |
684 case ENTRY_CONSTRUCT: | 708 case ENTRY_CONSTRUCT: |
685 case EXIT: | 709 case EXIT: |
| 710 case BUILTIN_EXIT: |
686 case STUB_FAILURE_TRAMPOLINE: | 711 case STUB_FAILURE_TRAMPOLINE: |
687 case ARGUMENTS_ADAPTOR: | 712 case ARGUMENTS_ADAPTOR: |
688 case STUB: | 713 case STUB: |
689 case INTERNAL: | 714 case INTERNAL: |
690 case CONSTRUCT: | 715 case CONSTRUCT: |
691 case JS_TO_WASM: | 716 case JS_TO_WASM: |
692 case WASM_TO_JS: | 717 case WASM_TO_JS: |
693 case WASM: | 718 case WASM: |
694 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp; | 719 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp; |
695 break; | 720 break; |
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1822 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1798 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1823 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1799 list.Add(frame, zone); | 1824 list.Add(frame, zone); |
1800 } | 1825 } |
1801 return list.ToVector(); | 1826 return list.ToVector(); |
1802 } | 1827 } |
1803 | 1828 |
1804 | 1829 |
1805 } // namespace internal | 1830 } // namespace internal |
1806 } // namespace v8 | 1831 } // namespace v8 |
OLD | NEW |