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