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

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: All platforms 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);
422 if (marker->IsSmi()) {
423 StackFrame::Type candidate =
424 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
425 switch (candidate) {
426 case ENTRY:
427 case ENTRY_CONSTRUCT:
428 case EXIT:
429 case STUB:
430 case STUB_FAILURE_TRAMPOLINE:
431 case INTERNAL:
432 case CONSTRUCT:
433 case ARGUMENTS_ADAPTOR:
434 case WASM_TO_JS:
titzer 2016/03/07 10:48:43 As discussed offline, if these two frame types don
danno 2016/03/08 07:04:44 Done.
435 case WASM:
436 return candidate;
437 case JAVA_SCRIPT:
438 case OPTIMIZED:
439 case INTERPRETED:
440 default:
441 // Unoptimized and optimized JavaScript frames, including interpreted
442 // frames, should never have a StackFrame::Type marker. If we find one,
443 // we're likely being called from the profiler in a bogus stack frame.
444 return NONE;
445 }
446 }
447
448 Object* maybe_function =
449 Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
420 if (!iterator->can_access_heap_objects_) { 450 if (!iterator->can_access_heap_objects_) {
421 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really 451 // 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 452 // means that we are being called from the profiler, which can interrupt
423 // the VM with a signal at any arbitrary instruction, with essentially 453 // the VM with a signal at any arbitrary instruction, with essentially
424 // anything on the stack. So basically none of these checks are 100% 454 // anything on the stack. So basically none of these checks are 100%
425 // reliable. 455 // reliable.
426 #if defined(USE_SIMULATOR) 456 #if defined(USE_SIMULATOR)
427 MSAN_MEMORY_IS_INITIALIZED( 457 MSAN_MEMORY_IS_INITIALIZED(
428 state->fp + StandardFrameConstants::kContextOffset, kPointerSize); 458 state->fp + StandardFrameConstants::kContextOffset, kPointerSize);
429 MSAN_MEMORY_IS_INITIALIZED( 459 MSAN_MEMORY_IS_INITIALIZED(
430 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize); 460 state->fp + StandardFrameConstants::kMarkerOffset, kPointerSize);
431 #endif 461 #endif
432 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 462 if (maybe_function->IsSmi()) {
433 // An adapter frame has a special SMI constant for the context and 463 return NONE;
434 // is not distinguished through the marker.
435 return ARGUMENTS_ADAPTOR;
436 }
437 Object* marker =
438 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset);
439 if (marker->IsSmi()) {
440 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
441 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(), 464 } else if (FLAG_ignition && IsInterpreterFramePc(iterator->isolate(),
442 *(state->pc_address))) { 465 *(state->pc_address))) {
443 return INTERPRETED; 466 return INTERPRETED;
444 } else { 467 } else {
445 return JAVA_SCRIPT; 468 return JAVA_SCRIPT;
446 } 469 }
447 } 470 }
448 471
449 // Look up the code object to figure out the type of the stack frame. 472 // Look up the code object to figure out the type of the stack frame.
450 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address)); 473 Code* code_obj = GetContainingCode(iterator->isolate(), *(state->pc_address));
451
452 Object* marker =
453 Memory::Object_at(state->fp + StandardFrameConstants::kMarkerOffset);
454 if (code_obj != nullptr) { 474 if (code_obj != nullptr) {
455 switch (code_obj->kind()) { 475 switch (code_obj->kind()) {
456 case Code::FUNCTION: 476 case Code::FUNCTION:
457 return JAVA_SCRIPT; 477 return JAVA_SCRIPT;
478 case Code::JS_TO_WASM_FUNCTION:
479 return JS_TO_WASM;
458 case Code::OPTIMIZED_FUNCTION: 480 case Code::OPTIMIZED_FUNCTION:
459 return OPTIMIZED; 481 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 case Code::BUILTIN: 482 case Code::BUILTIN:
467 if (!marker->IsSmi()) { 483 DCHECK(!maybe_function->IsSmi());
468 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 484 DCHECK(code_obj->is_interpreter_entry_trampoline() ||
469 // An adapter frame has a special SMI constant for the context and 485 code_obj->is_interpreter_enter_bytecode_dispatch());
470 // is not distinguished through the marker. 486 return INTERPRETED;
471 return ARGUMENTS_ADAPTOR;
472 } else {
473 // The interpreter entry trampoline has a non-SMI marker.
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: 487 default:
488 break; // Marker encodes the frame type. 488 // All other types should have an explicit marker
489 UNREACHABLE();
490 break;
489 } 491 }
490 } 492 }
491 493
492 // Didn't find a code object, or the code kind wasn't specific enough. 494 return NONE;
493 // The marker should encode the frame type.
494 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
495 } 495 }
496 496
497 497
498 #ifdef DEBUG 498 #ifdef DEBUG
499 bool StackFrame::can_access_heap_objects() const { 499 bool StackFrame::can_access_heap_objects() const {
500 return iterator_->can_access_heap_objects_; 500 return iterator_->can_access_heap_objects_;
501 } 501 }
502 #endif 502 #endif
503 503
504 504
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 572
573 void ExitFrame::Iterate(ObjectVisitor* v) const { 573 void ExitFrame::Iterate(ObjectVisitor* v) const {
574 // The arguments are traversed as part of the expression stack of 574 // The arguments are traversed as part of the expression stack of
575 // the calling frame. 575 // the calling frame.
576 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 576 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
577 v->VisitPointer(&code_slot()); 577 v->VisitPointer(&code_slot());
578 } 578 }
579 579
580 580
581 Address ExitFrame::GetCallerStackPointer() const { 581 Address ExitFrame::GetCallerStackPointer() const {
582 return fp() + ExitFrameConstants::kCallerSPDisplacement; 582 return fp() + ExitFrameConstants::kCallerSPOffset;
583 } 583 }
584 584
585 585
586 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { 586 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
587 if (fp == 0) return NONE; 587 if (fp == 0) return NONE;
588 Address sp = ComputeStackPointer(fp); 588 Address sp = ComputeStackPointer(fp);
589 FillState(fp, sp, state); 589 FillState(fp, sp, state);
590 DCHECK(*state->pc_address != NULL); 590 DCHECK(*state->pc_address != NULL);
591 return EXIT; 591 return EXIT;
592 } 592 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { 648 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
649 // Make sure that we're not doing "safe" stack frame iteration. We cannot 649 // Make sure that we're not doing "safe" stack frame iteration. We cannot
650 // possibly find pointers in optimized frames in that state. 650 // possibly find pointers in optimized frames in that state.
651 DCHECK(can_access_heap_objects()); 651 DCHECK(can_access_heap_objects());
652 652
653 // Compute the safepoint information. 653 // Compute the safepoint information.
654 unsigned stack_slots = 0; 654 unsigned stack_slots = 0;
655 SafepointEntry safepoint_entry; 655 SafepointEntry safepoint_entry;
656 Code* code = StackFrame::GetSafepointData( 656 Code* code = StackFrame::GetSafepointData(
657 isolate(), pc(), &safepoint_entry, &stack_slots); 657 isolate(), pc(), &safepoint_entry, &stack_slots);
658 unsigned slot_space = 658 unsigned slot_space = stack_slots * kPointerSize;
659 stack_slots * kPointerSize - StandardFrameConstants::kFixedFrameSize;
660 659
661 // Visit the outgoing parameters. 660 // Determine the fixed header and spill slot area size.
661 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
662 Object* marker = Memory::Object_at(fp() - kPointerSize);
663 if (marker->IsSmi()) {
664 StackFrame::Type candidate =
665 static_cast<StackFrame::Type>(Smi::cast(marker)->value());
666 switch (candidate) {
667 case ENTRY:
668 case ENTRY_CONSTRUCT:
669 case EXIT:
670 case STUB_FAILURE_TRAMPOLINE:
671 case ARGUMENTS_ADAPTOR:
672 case STUB:
673 case INTERNAL:
674 case CONSTRUCT:
675 case JS_TO_WASM:
676 case WASM_TO_JS:
677 case WASM:
678 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
679 break;
680 case JAVA_SCRIPT:
681 case OPTIMIZED:
682 case INTERPRETED:
683 // These frame types have a context, but they are actually stored
684 // in the place on the stack that one finds the frame type.
685 UNREACHABLE();
686 break;
687 case NONE:
688 case NUMBER_OF_TYPES:
689 case MANUAL:
690 UNREACHABLE();
691 break;
692 }
693 }
694 slot_space -=
695 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
696
697 Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
698 Object** frame_header_limit = &Memory::Object_at(fp());
662 Object** parameters_base = &Memory::Object_at(sp()); 699 Object** parameters_base = &Memory::Object_at(sp());
663 Object** parameters_limit = &Memory::Object_at( 700 Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
664 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
665 701
666 // Visit the parameters that may be on top of the saved registers. 702 // Visit the parameters that may be on top of the saved registers.
667 if (safepoint_entry.argument_count() > 0) { 703 if (safepoint_entry.argument_count() > 0) {
668 v->VisitPointers(parameters_base, 704 v->VisitPointers(parameters_base,
669 parameters_base + safepoint_entry.argument_count()); 705 parameters_base + safepoint_entry.argument_count());
670 parameters_base += safepoint_entry.argument_count(); 706 parameters_base += safepoint_entry.argument_count();
671 } 707 }
672 708
673 // Skip saved double registers. 709 // Skip saved double registers.
674 if (safepoint_entry.has_doubles()) { 710 if (safepoint_entry.has_doubles()) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 v->VisitPointer(parameters_limit + index); 743 v->VisitPointer(parameters_limit + index);
708 } 744 }
709 } 745 }
710 746
711 // Visit the return address in the callee and incoming arguments. 747 // Visit the return address in the callee and incoming arguments.
712 IteratePc(v, pc_address(), constant_pool_address(), code); 748 IteratePc(v, pc_address(), constant_pool_address(), code);
713 749
714 if (!is_wasm() && !is_wasm_to_js()) { 750 if (!is_wasm() && !is_wasm_to_js()) {
715 // Visit the context in stub frame and JavaScript frame. 751 // Visit the context in stub frame and JavaScript frame.
716 // Visit the function in JavaScript frame. 752 // Visit the function in JavaScript frame.
717 Object** fixed_base = 753 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 } 754 }
722 } 755 }
723 756
724 757
725 void StubFrame::Iterate(ObjectVisitor* v) const { 758 void StubFrame::Iterate(ObjectVisitor* v) const {
726 IterateCompiledFrame(v); 759 IterateCompiledFrame(v);
727 } 760 }
728 761
729 762
730 Code* StubFrame::unchecked_code() const { 763 Code* StubFrame::unchecked_code() const {
731 return static_cast<Code*>(isolate()->FindCodeObject(pc())); 764 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
732 } 765 }
733 766
734 767
735 Address StubFrame::GetCallerStackPointer() const { 768 Address StubFrame::GetCallerStackPointer() const {
736 return fp() + ExitFrameConstants::kCallerSPDisplacement; 769 return fp() + ExitFrameConstants::kCallerSPOffset;
737 } 770 }
738 771
739 772
740 int StubFrame::GetNumberOfIncomingArguments() const { 773 int StubFrame::GetNumberOfIncomingArguments() const {
741 return 0; 774 return 0;
742 } 775 }
743 776
744 777
745 void OptimizedFrame::Iterate(ObjectVisitor* v) const { 778 void OptimizedFrame::Iterate(ObjectVisitor* v) const {
746 IterateCompiledFrame(v); 779 IterateCompiledFrame(v);
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 accumulator->Add("wasm frame"); 1267 accumulator->Add("wasm frame");
1235 } 1268 }
1236 1269
1237 Code* WasmFrame::unchecked_code() const { 1270 Code* WasmFrame::unchecked_code() const {
1238 return static_cast<Code*>(isolate()->FindCodeObject(pc())); 1271 return static_cast<Code*>(isolate()->FindCodeObject(pc()));
1239 } 1272 }
1240 1273
1241 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); } 1274 void WasmFrame::Iterate(ObjectVisitor* v) const { IterateCompiledFrame(v); }
1242 1275
1243 Address WasmFrame::GetCallerStackPointer() const { 1276 Address WasmFrame::GetCallerStackPointer() const {
1244 return fp() + ExitFrameConstants::kCallerSPDisplacement; 1277 return fp() + ExitFrameConstants::kCallerSPOffset;
1245 } 1278 }
1246 1279
1247 namespace { 1280 namespace {
1248 1281
1249 1282
1250 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, 1283 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1251 Code* code) { 1284 Code* code) {
1252 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { 1285 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1253 std::ostringstream os; 1286 std::ostringstream os;
1254 os << "--------- s o u r c e c o d e ---------\n" 1287 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 { 1484 void InternalFrame::Iterate(ObjectVisitor* v) const {
1452 // Internal frames only have object pointers on the expression stack 1485 // Internal frames only have object pointers on the expression stack
1453 // as they never have any arguments. 1486 // as they never have any arguments.
1454 IterateExpressions(v); 1487 IterateExpressions(v);
1455 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 1488 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
1456 } 1489 }
1457 1490
1458 1491
1459 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const { 1492 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
1460 Object** base = &Memory::Object_at(sp()); 1493 Object** base = &Memory::Object_at(sp());
1461 Object** limit = &Memory::Object_at(fp() + 1494 Object** limit = &Memory::Object_at(
1462 kFirstRegisterParameterFrameOffset); 1495 fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset);
1463 v->VisitPointers(base, limit); 1496 v->VisitPointers(base, limit);
1464 base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset); 1497 base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset);
1465 const int offset = StandardFrameConstants::kLastObjectOffset; 1498 const int offset = StandardFrameConstants::kLastObjectOffset;
1466 limit = &Memory::Object_at(fp() + offset) + 1; 1499 limit = &Memory::Object_at(fp() + offset) + 1;
1467 v->VisitPointers(base, limit); 1500 v->VisitPointers(base, limit);
1468 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 1501 IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
1469 } 1502 }
1470 1503
1471 1504
1472 Address StubFailureTrampolineFrame::GetCallerStackPointer() const { 1505 Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
1473 return fp() + StandardFrameConstants::kCallerSPOffset; 1506 return fp() + StandardFrameConstants::kCallerSPOffset;
1474 } 1507 }
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { 1700 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1668 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); 1701 StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1669 list.Add(frame, zone); 1702 list.Add(frame, zone);
1670 } 1703 }
1671 return list.ToVector(); 1704 return list.ToVector();
1672 } 1705 }
1673 1706
1674 1707
1675 } // namespace internal 1708 } // namespace internal
1676 } // namespace v8 1709 } // namespace v8
OLDNEW
« src/compiler/arm/code-generator-arm.cc ('K') | « src/frames.h ('k') | src/frames-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698