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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 } else if (IsValidStackAddress(fp)) { | 209 } else if (IsValidStackAddress(fp)) { |
210 DCHECK(fp != NULL); | 210 DCHECK(fp != NULL); |
211 state.fp = fp; | 211 state.fp = fp; |
212 state.sp = sp; | 212 state.sp = sp; |
213 state.pc_address = StackFrame::ResolveReturnAddressLocation( | 213 state.pc_address = StackFrame::ResolveReturnAddressLocation( |
214 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); | 214 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); |
215 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, | 215 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, |
216 // we check only that kMarkerOffset is within the stack bounds and do | 216 // we check only that kMarkerOffset is within the stack bounds and do |
217 // compile time check that kContextOffset slot is pushed on the stack before | 217 // compile time check that kContextOffset slot is pushed on the stack before |
218 // kMarkerOffset. | 218 // kMarkerOffset. |
219 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset < | 219 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset < |
220 StandardFrameConstants::kContextOffset); | 220 StandardFrameConstants::kContextOffset); |
221 Address frame_marker = fp + StandardFrameConstants::kMarkerOffset; | 221 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset; |
222 if (IsValidStackAddress(frame_marker)) { | 222 if (IsValidStackAddress(frame_marker)) { |
223 type = StackFrame::ComputeType(this, &state); | 223 type = StackFrame::ComputeType(this, &state); |
224 top_frame_type_ = type; | 224 top_frame_type_ = type; |
225 } else { | 225 } else { |
226 // Mark the frame as JAVA_SCRIPT if we cannot determine its type. | 226 // Mark the frame as JAVA_SCRIPT if we cannot determine its type. |
227 // The frame anyways will be skipped. | 227 // The frame anyways will be skipped. |
228 type = StackFrame::JAVA_SCRIPT; | 228 type = StackFrame::JAVA_SCRIPT; |
229 // Top frame is incomplete so we cannot reliably determine its type. | 229 // Top frame is incomplete so we cannot reliably determine its type. |
230 top_frame_type_ = StackFrame::NONE; | 230 top_frame_type_ = StackFrame::NONE; |
231 } | 231 } |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 ReturnAddressLocationResolver resolver) { | 401 ReturnAddressLocationResolver resolver) { |
402 DCHECK(return_address_location_resolver_ == NULL); | 402 DCHECK(return_address_location_resolver_ == NULL); |
403 return_address_location_resolver_ = resolver; | 403 return_address_location_resolver_ = resolver; |
404 } | 404 } |
405 | 405 |
406 | 406 |
407 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, | 407 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, |
408 State* state) { | 408 State* state) { |
409 DCHECK(state->fp != NULL); | 409 DCHECK(state->fp != NULL); |
410 | 410 |
411 Object* marker = Memory::Object_at( | |
412 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); | |
413 if (marker->IsSmi()) { | |
414 StackFrame::Type candidate = | |
415 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | |
416 switch (candidate) { | |
417 case ENTRY: | |
418 case ENTRY_CONSTRUCT: | |
419 case EXIT: | |
420 case STUB: | |
421 case STUB_FAILURE_TRAMPOLINE: | |
422 case INTERNAL: | |
423 case CONSTRUCT: | |
424 case ARGUMENTS_ADAPTOR: | |
425 return candidate; | |
426 case JAVA_SCRIPT: | |
427 case OPTIMIZED: | |
428 case INTERPRETED: | |
429 default: | |
430 // Unoptimized and optimized JavaScript frames, including interpreted | |
431 // frames, should never have a StackFrame::Type marker. If we find one, | |
432 // we're likely being called from the profiler in a bogus stack frame. | |
433 return NONE; | |
434 } | |
435 } | |
436 | |
437 Object* maybe_function = | |
438 Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset); | |
411 if (!iterator->can_access_heap_objects_) { | 439 if (!iterator->can_access_heap_objects_) { |
412 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really | 440 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really |
413 // means that we are being called from the profiler, which can interrupt | 441 // means that we are being called from the profiler, which can interrupt |
414 // the VM with a signal at any arbitrary instruction, with essentially | 442 // the VM with a signal at any arbitrary instruction, with essentially |
415 // anything on the stack. So basically none of these checks are 100% | 443 // anything on the stack. So basically none of these checks are 100% |
416 // reliable. | 444 // reliable. |
417 #if defined(USE_SIMULATOR) | 445 #if defined(USE_SIMULATOR) |
418 MSAN_MEMORY_IS_INITIALIZED( | 446 MSAN_MEMORY_IS_INITIALIZED( |
419 state->fp + StandardFrameConstants::kContextOffset, kPointerSize); | 447 state->fp + StandardFrameConstants::kContextOffset, kPointerSize); |
420 MSAN_MEMORY_IS_INITIALIZED( | 448 MSAN_MEMORY_IS_INITIALIZED( |
421 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize); | 449 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize); |
422 #endif | 450 #endif |
423 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { | 451 if (maybe_function->IsSmi()) { |
424 // An adapter frame has a special SMI constant for the context and | 452 return NONE; |
425 // is not distinguished through the marker. | |
426 return ARGUMENTS_ADAPTOR; | |
427 } | |
428 Object* marker = | |
429 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset); | |
430 if (marker->IsSmi()) { | |
431 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | |
432 } else { | 453 } else { |
433 return JAVA_SCRIPT; | 454 return JAVA_SCRIPT; |
434 } | 455 } |
435 } | 456 } |
436 | 457 |
437 // Look up the code object to figure out the type of the stack frame. | 458 // Look up the code object to figure out the type of the stack frame. |
438 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address)); | 459 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address)); |
439 | |
440 Object* marker = | |
441 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset); | |
442 if (code_obj != nullptr) { | 460 if (code_obj != nullptr) { |
443 switch (code_obj->kind()) { | 461 switch (code_obj->kind()) { |
444 case Code::FUNCTION: | 462 case Code::FUNCTION: |
445 return JAVA_SCRIPT; | 463 return JAVA_SCRIPT; |
446 case Code::OPTIMIZED_FUNCTION: | 464 case Code::OPTIMIZED_FUNCTION: |
447 return OPTIMIZED; | 465 return OPTIMIZED; |
448 case Code::WASM_FUNCTION: | 466 case Code::WASM_FUNCTION: |
449 return STUB; | 467 return STUB; |
450 case Code::BUILTIN: | 468 case Code::BUILTIN: |
451 if (!marker->IsSmi()) { | 469 DCHECK(!maybe_function->IsSmi()); |
452 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { | 470 DCHECK(code_obj->is_interpreter_entry_trampoline() || |
453 // An adapter frame has a special SMI constant for the context and | 471 code_obj->is_interpreter_enter_bytecode_dispatch()); |
454 // is not distinguished through the marker. | 472 return INTERPRETED; |
455 return ARGUMENTS_ADAPTOR; | |
456 } else { | |
457 // The interpreter entry trampoline has a non-SMI marker. | |
458 DCHECK(code_obj->is_interpreter_entry_trampoline() || | |
459 code_obj->is_interpreter_enter_bytecode_dispatch()); | |
460 return INTERPRETED; | |
461 } | |
462 } | |
463 break; // Marker encodes the frame type. | |
464 case Code::HANDLER: | |
465 if (!marker->IsSmi()) { | |
466 // Only hydrogen code stub handlers can have a non-SMI marker. | |
467 DCHECK(code_obj->is_hydrogen_stub()); | |
468 return OPTIMIZED; | |
469 } | |
470 break; // Marker encodes the frame type. | |
471 default: | 473 default: |
472 break; // Marker encodes the frame type. | 474 // All other types should have an explicit marker |
475 UNREACHABLE(); | |
476 break; | |
473 } | 477 } |
474 } | 478 } |
475 | 479 |
476 // Didn't find a code object, or the code kind wasn't specific enough. | 480 return NONE; |
477 // The marker should encode the frame type. | |
478 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | |
479 } | 481 } |
480 | 482 |
481 | 483 |
482 #ifdef DEBUG | 484 #ifdef DEBUG |
483 bool StackFrame::can_access_heap_objects() const { | 485 bool StackFrame::can_access_heap_objects() const { |
484 return iterator_->can_access_heap_objects_; | 486 return iterator_->can_access_heap_objects_; |
485 } | 487 } |
486 #endif | 488 #endif |
487 | 489 |
488 | 490 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
641 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 643 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
642 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 644 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
643 // possibly find pointers in optimized frames in that state. | 645 // possibly find pointers in optimized frames in that state. |
644 DCHECK(can_access_heap_objects()); | 646 DCHECK(can_access_heap_objects()); |
645 | 647 |
646 // Compute the safepoint information. | 648 // Compute the safepoint information. |
647 unsigned stack_slots = 0; | 649 unsigned stack_slots = 0; |
648 SafepointEntry safepoint_entry; | 650 SafepointEntry safepoint_entry; |
649 Code* code = StackFrame::GetSafepointData( | 651 Code* code = StackFrame::GetSafepointData( |
650 isolate(), pc(), &safepoint_entry, &stack_slots); | 652 isolate(), pc(), &safepoint_entry, &stack_slots); |
651 unsigned slot_space = | 653 unsigned slot_space = stack_slots * kPointerSize; |
652 stack_slots * kPointerSize - StandardFrameConstants::kFixedFrameSize; | |
653 | 654 |
654 // Visit the outgoing parameters. | 655 // Visit the outgoing parameters. |
Michael Starzinger
2016/02/23 10:57:33
nit: Comment is outdated.
danno
2016/03/07 09:33:38
Done.
| |
656 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp; | |
657 Object* marker = Memory::Object_at(fp() - kPointerSize); | |
658 if (marker->IsSmi()) { | |
659 StackFrame::Type candidate = | |
660 static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | |
661 switch (candidate) { | |
662 case ENTRY: | |
663 case ENTRY_CONSTRUCT: | |
664 case EXIT: | |
665 case STUB_FAILURE_TRAMPOLINE: | |
666 case ARGUMENTS_ADAPTOR: | |
667 case STUB: | |
668 case INTERNAL: | |
669 case CONSTRUCT: | |
670 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp; | |
671 break; | |
672 case JAVA_SCRIPT: | |
673 case OPTIMIZED: | |
674 case INTERPRETED: | |
675 // These frame types have a context, but they are actually stored | |
676 // in the place on the stack that one finds the frame type. | |
677 UNREACHABLE(); | |
678 break; | |
679 case NONE: | |
680 case NUMBER_OF_TYPES: | |
681 case MANUAL: | |
682 UNREACHABLE(); | |
683 break; | |
684 } | |
685 } | |
686 slot_space -= | |
687 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp); | |
688 | |
689 Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size); | |
690 Object** frame_header_limit = &Memory::Object_at(fp()); | |
655 Object** parameters_base = &Memory::Object_at(sp()); | 691 Object** parameters_base = &Memory::Object_at(sp()); |
656 Object** parameters_limit = &Memory::Object_at( | 692 Object** parameters_limit = frame_header_base - slot_space / kPointerSize; |
657 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); | |
658 | 693 |
659 // Visit the parameters that may be on top of the saved registers. | 694 // Visit the parameters that may be on top of the saved registers. |
660 if (safepoint_entry.argument_count() > 0) { | 695 if (safepoint_entry.argument_count() > 0) { |
661 v->VisitPointers(parameters_base, | 696 v->VisitPointers(parameters_base, |
662 parameters_base + safepoint_entry.argument_count()); | 697 parameters_base + safepoint_entry.argument_count()); |
663 parameters_base += safepoint_entry.argument_count(); | 698 parameters_base += safepoint_entry.argument_count(); |
664 } | 699 } |
665 | 700 |
666 // Skip saved double registers. | 701 // Skip saved double registers. |
667 if (safepoint_entry.has_doubles()) { | 702 if (safepoint_entry.has_doubles()) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
699 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) { | 734 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) { |
700 v->VisitPointer(parameters_limit + index); | 735 v->VisitPointer(parameters_limit + index); |
701 } | 736 } |
702 } | 737 } |
703 | 738 |
704 // Visit the return address in the callee and incoming arguments. | 739 // Visit the return address in the callee and incoming arguments. |
705 IteratePc(v, pc_address(), constant_pool_address(), code); | 740 IteratePc(v, pc_address(), constant_pool_address(), code); |
706 | 741 |
707 // Visit the context in stub frame and JavaScript frame. | 742 // Visit the context in stub frame and JavaScript frame. |
708 // Visit the function in JavaScript frame. | 743 // Visit the function in JavaScript frame. |
709 Object** fixed_base = &Memory::Object_at( | 744 v->VisitPointers(frame_header_base, frame_header_limit); |
710 fp() + StandardFrameConstants::kMarkerOffset); | |
711 Object** fixed_limit = &Memory::Object_at(fp()); | |
712 v->VisitPointers(fixed_base, fixed_limit); | |
713 } | 745 } |
714 | 746 |
715 | 747 |
716 void StubFrame::Iterate(ObjectVisitor* v) const { | 748 void StubFrame::Iterate(ObjectVisitor* v) const { |
717 IterateCompiledFrame(v); | 749 IterateCompiledFrame(v); |
718 } | 750 } |
719 | 751 |
720 | 752 |
721 Code* StubFrame::unchecked_code() const { | 753 Code* StubFrame::unchecked_code() const { |
722 return static_cast<Code*>(isolate()->FindCodeObject(pc())); | 754 return static_cast<Code*>(isolate()->FindCodeObject(pc())); |
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1430 void InternalFrame::Iterate(ObjectVisitor* v) const { | 1462 void InternalFrame::Iterate(ObjectVisitor* v) const { |
1431 // Internal frames only have object pointers on the expression stack | 1463 // Internal frames only have object pointers on the expression stack |
1432 // as they never have any arguments. | 1464 // as they never have any arguments. |
1433 IterateExpressions(v); | 1465 IterateExpressions(v); |
1434 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); | 1466 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
1435 } | 1467 } |
1436 | 1468 |
1437 | 1469 |
1438 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { | 1470 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { |
1439 Object** base = &Memory::Object_at(sp()); | 1471 Object** base = &Memory::Object_at(sp()); |
1440 Object** limit = &Memory::Object_at(fp() + | 1472 Object** limit = &Memory::Object_at( |
1441 kFirstRegisterParameterFrameOffset); | 1473 fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset); |
1442 v->VisitPointers(base, limit); | 1474 v->VisitPointers(base, limit); |
1443 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset); | 1475 base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset); |
1444 const int offset = StandardFrameConstants::kLastObjectOffset; | 1476 const int offset = StandardFrameConstants::kLastObjectOffset; |
1445 limit = &Memory::Object_at(fp() + offset) + 1; | 1477 limit = &Memory::Object_at(fp() + offset) + 1; |
1446 v->VisitPointers(base, limit); | 1478 v->VisitPointers(base, limit); |
1447 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); | 1479 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); |
1448 } | 1480 } |
1449 | 1481 |
1450 | 1482 |
1451 Address StubFailureTrampolineFrame::GetCallerStackPointer() const { | 1483 Address StubFailureTrampolineFrame::GetCallerStackPointer() const { |
1452 return fp() + StandardFrameConstants::kCallerSPOffset; | 1484 return fp() + StandardFrameConstants::kCallerSPOffset; |
1453 } | 1485 } |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1646 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1678 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1647 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1679 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1648 list.Add(frame, zone); | 1680 list.Add(frame, zone); |
1649 } | 1681 } |
1650 return list.ToVector(); | 1682 return list.ToVector(); |
1651 } | 1683 } |
1652 | 1684 |
1653 | 1685 |
1654 } // namespace internal | 1686 } // namespace internal |
1655 } // namespace v8 | 1687 } // namespace v8 |
OLD | NEW |