Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: src/frames.cc

Issue 1696043002: [runtime] Unify and simplify how frames are marked (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix merge problems Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 } else if (IsValidStackAddress(fp)) { 207 } else if (IsValidStackAddress(fp)) {
208 DCHECK(fp != NULL); 208 DCHECK(fp != NULL);
209 state.fp = fp; 209 state.fp = fp;
210 state.sp = sp; 210 state.sp = sp;
211 state.pc_address = StackFrame::ResolveReturnAddressLocation( 211 state.pc_address = StackFrame::ResolveReturnAddressLocation(
212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); 212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, 213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
214 // we check only that kMarkerOffset is within the stack bounds and do 214 // we check only that kMarkerOffset is within the stack bounds and do
215 // compile time check that kContextOffset slot is pushed on the stack before 215 // compile time check that kContextOffset slot is pushed on the stack before
216 // kMarkerOffset. 216 // kMarkerOffset.
217 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset < 217 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
218 StandardFrameConstants::kContextOffset); 218 StandardFrameConstants::kContextOffset);
219 Address frame_marker = fp + StandardFrameConstants::kMarkerOffset; 219 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
220 if (IsValidStackAddress(frame_marker)) { 220 if (IsValidStackAddress(frame_marker)) {
221 type = StackFrame::ComputeType(this, &state); 221 type = StackFrame::ComputeType(this, &state);
222 top_frame_type_ = type; 222 top_frame_type_ = type;
223 } else { 223 } else {
224 // Mark the frame as JAVA_SCRIPT if we cannot determine its type. 224 // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
225 // The frame anyways will be skipped. 225 // The frame anyways will be skipped.
226 type = StackFrame::JAVA_SCRIPT; 226 type = StackFrame::JAVA_SCRIPT;
227 // Top frame is incomplete so we cannot reliably determine its type. 227 // Top frame is incomplete so we cannot reliably determine its type.
228 top_frame_type_ = StackFrame::NONE; 228 top_frame_type_ = StackFrame::NONE;
229 } 229 }
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 return (pc >= interpreter_entry_trampoline->instruction_start() && 410 return (pc >= interpreter_entry_trampoline->instruction_start() &&
411 pc < interpreter_entry_trampoline->instruction_end()) || 411 pc < interpreter_entry_trampoline->instruction_end()) ||
412 (pc >= interpreter_bytecode_dispatch->instruction_start() && 412 (pc >= interpreter_bytecode_dispatch->instruction_start() &&
413 pc < interpreter_bytecode_dispatch->instruction_end()); 413 pc < interpreter_bytecode_dispatch->instruction_end());
414 } 414 }
415 415
416 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, 416 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
417 State* state) { 417 State* state) {
418 DCHECK(state->fp != NULL); 418 DCHECK(state->fp != NULL);
419 419
420 Object* marker = Memory::Object_at(
421 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
420 if (!iterator->can_access_heap_objects_) { 422 if (!iterator->can_access_heap_objects_) {
421 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really 423 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
422 // means that we are being called from the profiler, which can interrupt 424 // means that we are being called from the profiler, which can interrupt
423 // the VM with a signal at any arbitrary instruction, with essentially 425 // the VM with a signal at any arbitrary instruction, with essentially
424 // anything on the stack. So basically none of these checks are 100% 426 // anything on the stack. So basically none of these checks are 100%
425 // reliable. 427 // reliable.
426 #if defined(USE_SIMULATOR) 428 #if defined(USE_SIMULATOR)
427 MSAN_MEMORY_IS_INITIALIZED( 429 MSAN_MEMORY_IS_INITIALIZED(
428 state->fp + StandardFrameConstants::kContextOffset, kPointerSize); 430 state->fp + StandardFrameConstants::kContextOffset, kPointerSize);
429 MSAN_MEMORY_IS_INITIALIZED( 431 MSAN_MEMORY_IS_INITIALIZED(
430 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize); 432 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize);
431 #endif 433 #endif
432 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 434 Object* maybe_function =
433 // An adapter frame has a special SMI constant for the context and 435 Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
434 // is not distinguished through the marker. 436 if (!marker->IsSmi()) {
435 return ARGUMENTS_ADAPTOR; 437 if (maybe_function->IsSmi()) {
438 return NONE;
439 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(),
440 *(state->pc_address))) {
441 return INTERPRETED;
442 } else {
443 return JAVA_SCRIPT;
444 }
436 } 445 }
437 Object* marker = 446 } else {
438 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset); 447 // Look up the code object to figure out the type of the stack frame.
439 if (marker->IsSmi()) { 448 Code* code_obj =
440 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); 449 GetContainingCode(iterator->isolate(), *(state->pc_address));
441 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(), 450 if (code_obj != nullptr) {
442 *(state->pc_address))) { 451 if (code_obj->is_interpreter_entry_trampoline() ||
443 return INTERPRETED; 452 code_obj->is_interpreter_enter_bytecode_dispatch()) {
453 return INTERPRETED;
454 }
455 switch (code_obj->kind()) {
456 case Code::FUNCTION:
457 return JAVA_SCRIPT;
458 case Code::OPTIMIZED_FUNCTION:
459 return OPTIMIZED;
460 case Code::WASM_FUNCTION:
461 return WASM;
462 case Code::WASM_TO_JS_FUNCTION:
463 return WASM_TO_JS;
464 case Code::JS_TO_WASM_FUNCTION:
465 return JS_TO_WASM;
466 default:
467 // All other types should have an explicit marker
468 break;
469 }
444 } else { 470 } else {
445 return JAVA_SCRIPT; 471 return NONE;
446 } 472 }
447 } 473 }
448 474
449 // Look up the code object to figure out the type of the stack frame. 475 DCHECK(marker->IsSmi());
450 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address)); 476 StackFrame::Type candidate =
451 477 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
452 Object* marker = 478 switch (candidate) {
453 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset); 479 case ENTRY:
454 if (code_obj != nullptr) { 480 case ENTRY_CONSTRUCT:
455 switch (code_obj->kind()) { 481 case EXIT:
456 case Code::FUNCTION: 482 case STUB:
457 return JAVA_SCRIPT; 483 case STUB_FAILURE_TRAMPOLINE:
458 case Code::OPTIMIZED_FUNCTION: 484 case INTERNAL:
459 return OPTIMIZED; 485 case CONSTRUCT:
460 case Code::WASM_FUNCTION: 486 case ARGUMENTS_ADAPTOR:
461 return WASM; 487 return candidate;
462 case Code::WASM_TO_JS_FUNCTION: 488 case JS_TO_WASM:
463 return WASM_TO_JS; 489 case WASM_TO_JS:
464 case Code::JS_TO_WASM_FUNCTION: 490 case WASM:
465 return JS_TO_WASM; 491 case JAVA_SCRIPT:
466 case Code::BUILTIN: 492 case OPTIMIZED:
467 if (!marker->IsSmi()) { 493 case INTERPRETED:
468 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 494 default:
469 // An adapter frame has a special SMI constant for the context and 495 // Unoptimized and optimized JavaScript frames, including
470 // is not distinguished through the marker. 496 // interpreted frames, should never have a StackFrame::Type
471 return ARGUMENTS_ADAPTOR; 497 // marker. If we find one, we're likely being called from the
472 } else { 498 // profiler in a bogus stack frame.
473 // The interpreter entry trampoline has a non-SMI marker. 499 return NONE;
474 DCHECK(code_obj->is_interpreter_entry_trampoline() ||
475 code_obj->is_interpreter_enter_bytecode_dispatch());
476 return INTERPRETED;
477 }
478 }
479 break; // Marker encodes the frame type.
480 case Code::HANDLER:
481 if (!marker->IsSmi()) {
482 // Only hydrogen code stub handlers can have a non-SMI marker.
483 DCHECK(code_obj->is_hydrogen_stub());
484 return OPTIMIZED;
485 }
486 break; // Marker encodes the frame type.
487 default:
488 break; // Marker encodes the frame type.
489 }
490 } 500 }
491
492 // Didn't find a code object, or the code kind wasn't specific enough.
493 // The marker should encode the frame type.
494 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
495 } 501 }
496 502
497 503
498 #ifdef DEBUG 504 #ifdef DEBUG
499 bool StackFrame::can_access_heap_objects() const { 505 bool StackFrame::can_access_heap_objects() const {
500 return iterator_->can_access_heap_objects_; 506 return iterator_->can_access_heap_objects_;
501 } 507 }
502 #endif 508 #endif
503 509
504 510
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 578
573 void ExitFrame::Iterate(ObjectVisitor* v) const { 579 void ExitFrame::Iterate(ObjectVisitor* v) const {
574 // The arguments are traversed as part of the expression stack of 580 // The arguments are traversed as part of the expression stack of
575 // the calling frame. 581 // the calling frame.
576 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 582 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
577 v->VisitPointer(&code_slot()); 583 v->VisitPointer(&code_slot());
578 } 584 }
579 585
580 586
581 Address ExitFrame::GetCallerStackPointer() const { 587 Address ExitFrame::GetCallerStackPointer() const {
582 return fp() + ExitFrameConstants::kCallerSPDisplacement; 588 return fp() + ExitFrameConstants::kCallerSPOffset;
583 } 589 }
584 590
585 591
586 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { 592 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
587 if (fp == 0) return NONE; 593 if (fp == 0) return NONE;
588 Address sp = ComputeStackPointer(fp); 594 Address sp = ComputeStackPointer(fp);
589 FillState(fp, sp, state); 595 FillState(fp, sp, state);
590 DCHECK(*state->pc_address != NULL); 596 DCHECK(*state->pc_address != NULL);
591 return EXIT; 597 return EXIT;
592 } 598 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { 654 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
649 // Make sure that we're not doing "safe" stack frame iteration. We cannot 655 // Make sure that we're not doing "safe" stack frame iteration. We cannot
650 // possibly find pointers in optimized frames in that state. 656 // possibly find pointers in optimized frames in that state.
651 DCHECK(can_access_heap_objects()); 657 DCHECK(can_access_heap_objects());
652 658
653 // Compute the safepoint information. 659 // Compute the safepoint information.
654 unsigned stack_slots = 0; 660 unsigned stack_slots = 0;
655 SafepointEntry safepoint_entry; 661 SafepointEntry safepoint_entry;
656 Code* code = StackFrame::GetSafepointData( 662 Code* code = StackFrame::GetSafepointData(
657 isolate(), pc(), &safepoint_entry, &stack_slots); 663 isolate(), pc(), &safepoint_entry, &stack_slots);
658 unsigned slot_space = 664 unsigned slot_space = stack_slots * kPointerSize;
659 stack_slots * kPointerSize - StandardFrameConstants::kFixedFrameSize;
660 665
661 // Visit the outgoing parameters. 666 // Determine the fixed header and spill slot area size.
667 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
668 Object* marker = Memory::Object_at(fp() - kPointerSize);
669 if (marker->IsSmi()) {
670 StackFrame::Type candidate =
671 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
672 switch (candidate) {
673 case ENTRY:
674 case ENTRY_CONSTRUCT:
675 case EXIT:
676 case STUB_FAILURE_TRAMPOLINE:
677 case ARGUMENTS_ADAPTOR:
678 case STUB:
679 case INTERNAL:
680 case CONSTRUCT:
681 case JS_TO_WASM:
682 case WASM_TO_JS:
683 case WASM:
684 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
685 break;
686 case JAVA_SCRIPT:
687 case OPTIMIZED:
688 case INTERPRETED:
689 // These frame types have a context, but they are actually stored
690 // in the place on the stack that one finds the frame type.
691 UNREACHABLE();
692 break;
693 case NONE:
694 case NUMBER_OF_TYPES:
695 case MANUAL:
696 UNREACHABLE();
697 break;
698 }
699 }
700 slot_space -=
701 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
702
703 Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
704 Object** frame_header_limit = &Memory::Object_at(fp());
662 Object** parameters_base = &Memory::Object_at(sp()); 705 Object** parameters_base = &Memory::Object_at(sp());
663 Object** parameters_limit = &Memory::Object_at( 706 Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
664 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
665 707
666 // Visit the parameters that may be on top of the saved registers. 708 // Visit the parameters that may be on top of the saved registers.
667 if (safepoint_entry.argument_count() > 0) { 709 if (safepoint_entry.argument_count() > 0) {
668 v->VisitPointers(parameters_base, 710 v->VisitPointers(parameters_base,
669 parameters_base + safepoint_entry.argument_count()); 711 parameters_base + safepoint_entry.argument_count());
670 parameters_base += safepoint_entry.argument_count(); 712 parameters_base += safepoint_entry.argument_count();
671 } 713 }
672 714
673 // Skip saved double registers. 715 // Skip saved double registers.
674 if (safepoint_entry.has_doubles()) { 716 if (safepoint_entry.has_doubles()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 v->VisitPointer(parameters_limit + index); 749 v->VisitPointer(parameters_limit + index);
708 } 750 }
709 } 751 }
710 752
711 // Visit the return address in the callee and incoming arguments. 753 // Visit the return address in the callee and incoming arguments.
712 IteratePc(v, pc_address(), constant_pool_address(), code); 754 IteratePc(v, pc_address(), constant_pool_address(), code);
713 755
714 if (!is_wasm() && !is_wasm_to_js()) { 756 if (!is_wasm() && !is_wasm_to_js()) {
715 // Visit the context in stub frame and JavaScript frame. 757 // Visit the context in stub frame and JavaScript frame.
716 // Visit the function in JavaScript frame. 758 // Visit the function in JavaScript frame.
717 Object** fixed_base = 759 v->VisitPointers(frame_header_base, frame_header_limit);
718 &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
719 Object** fixed_limit = &Memory::Object_at(fp());
720 v->VisitPointers(fixed_base, fixed_limit);
721 } 760 }
722 } 761 }
723 762
724 763
725 void StubFrame::Iterate(ObjectVisitor* v) const { 764 void StubFrame::Iterate(ObjectVisitor* v) const {
726 IterateCompiledFrame(v); 765 IterateCompiledFrame(v);
727 } 766 }
728 767
729 768
730 Code* StubFrame::unchecked_code() const { 769 Code* StubFrame::unchecked_code() const {
731 return static_cast<Code*>(isolate()->FindCodeObject(pc())); 770 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
732 } 771 }
733 772
734 773
735 Address StubFrame::GetCallerStackPointer() const { 774 Address StubFrame::GetCallerStackPointer() const {
736 return fp() + ExitFrameConstants::kCallerSPDisplacement; 775 return fp() + ExitFrameConstants::kCallerSPOffset;
737 } 776 }
738 777
739 778
740 int StubFrame::GetNumberOfIncomingArguments() const { 779 int StubFrame::GetNumberOfIncomingArguments() const {
741 return 0; 780 return 0;
742 } 781 }
743 782
744 783
745 void OptimizedFrame::Iterate(ObjectVisitor* v) const { 784 void OptimizedFrame::Iterate(ObjectVisitor* v) const {
746 IterateCompiledFrame(v); 785 IterateCompiledFrame(v);
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 accumulator->Add("wasm frame"); 1273 accumulator->Add("wasm frame");
1235 } 1274 }
1236 1275
1237 Code* WasmFrame::unchecked_code() const { 1276 Code* WasmFrame::unchecked_code() const {
1238 return static_cast<Code*>(isolate()->FindCodeObject(pc())); 1277 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
1239 } 1278 }
1240 1279
1241 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } 1280 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
1242 1281
1243 Address WasmFrame::GetCallerStackPointer() const { 1282 Address WasmFrame::GetCallerStackPointer() const {
1244 return fp() + ExitFrameConstants::kCallerSPDisplacement; 1283 return fp() + ExitFrameConstants::kCallerSPOffset;
1245 } 1284 }
1246 1285
1247 namespace { 1286 namespace {
1248 1287
1249 1288
1250 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, 1289 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1251 Code* code) { 1290 Code* code) {
1252 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { 1291 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1253 std::ostringstream os; 1292 std::ostringstream os;
1254 os << "--------- s o u r c e c o d e ---------\n" 1293 os << "--------- s o u r c e c o d e ---------\n"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 void InternalFrame::Iterate(ObjectVisitor* v) const { 1490 void InternalFrame::Iterate(ObjectVisitor* v) const {
1452 // Internal frames only have object pointers on the expression stack 1491 // Internal frames only have object pointers on the expression stack
1453 // as they never have any arguments. 1492 // as they never have any arguments.
1454 IterateExpressions(v); 1493 IterateExpressions(v);
1455 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 1494 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
1456 } 1495 }
1457 1496
1458 1497
1459 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { 1498 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1460 Object** base = &Memory::Object_at(sp()); 1499 Object** base = &Memory::Object_at(sp());
1461 Object** limit = &Memory::Object_at(fp() + 1500 Object** limit = &Memory::Object_at(
1462 kFirstRegisterParameterFrameOffset); 1501 fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset);
1463 v->VisitPointers(base, limit); 1502 v->VisitPointers(base, limit);
1464 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset); 1503 base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset);
1465 const int offset = StandardFrameConstants::kLastObjectOffset; 1504 const int offset = StandardFrameConstants::kLastObjectOffset;
1466 limit = &Memory::Object_at(fp() + offset) + 1; 1505 limit = &Memory::Object_at(fp() + offset) + 1;
1467 v->VisitPointers(base, limit); 1506 v->VisitPointers(base, limit);
1468 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 1507 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
1469 } 1508 }
1470 1509
1471 1510
1472 Address StubFailureTrampolineFrame::GetCallerStackPointer() const { 1511 Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1473 return fp() + StandardFrameConstants::kCallerSPOffset; 1512 return fp() + StandardFrameConstants::kCallerSPOffset;
1474 } 1513 }
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { 1706 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1668 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); 1707 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1669 list.Add(frame, zone); 1708 list.Add(frame, zone);
1670 } 1709 }
1671 return list.ToVector(); 1710 return list.ToVector();
1672 } 1711 }
1673 1712
1674 1713
1675 } // namespace internal 1714 } // namespace internal
1676 } // namespace v8 1715 } // namespace v8
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/frames-inl.h » ('j') | src/x64/macro-assembler-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698