1// Copyright 2020 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/heap/conservative-stack-visitor.h" 6 7#include "src/execution/isolate-utils-inl.h" 8#include "src/heap/large-spaces.h" 9#include "src/heap/paged-spaces-inl.h" 10 11namespace v8 { 12namespace internal { 13 14ConservativeStackVisitor::ConservativeStackVisitor(Isolate* isolate, 15 RootVisitor* delegate) 16 : isolate_(isolate), delegate_(delegate) {} 17 18void ConservativeStackVisitor::VisitPointer(const void* pointer) { 19 VisitConservativelyIfPointer(pointer); 20} 21 22bool ConservativeStackVisitor::CheckPage(Address address, MemoryChunk* page) { 23 if (address < page->area_start() || address >= page->area_end()) return false; 24 25 auto base_ptr = page->object_start_bitmap()->FindBasePtr(address); 26 if (base_ptr == kNullAddress) { 27 return false; 28 } 29 30 // At this point, base_ptr *must* refer to the valid object. We check if 31 // |address| resides inside the object or beyond it in unused memory. 32 HeapObject obj = HeapObject::FromAddress(base_ptr); 33 Address obj_end = obj.address() + obj.Size(); 34 35 if (address >= obj_end) { 36 // |address| points to unused memory. 37 return false; 38 } 39 40 // TODO(jakehughes) Pinning is only required for the marking visitor. Other 41 // visitors (such as verify visitor) could work without pining. This should 42 // be moved to delegate_ 43 page->SetFlag(BasicMemoryChunk::Flag::PINNED); 44 45 Object ptr = HeapObject::FromAddress(base_ptr); 46 FullObjectSlot root = FullObjectSlot(&ptr); 47 delegate_->VisitRootPointer(Root::kHandleScope, nullptr, root); 48 DCHECK(root == FullObjectSlot(reinterpret_cast<Address>(&base_ptr))); 49 return true; 50} 51 52void ConservativeStackVisitor::VisitConservativelyIfPointer( 53 const void* pointer) { 54 auto address = reinterpret_cast<Address>(pointer); 55 if (address > isolate_->heap()->old_space()->top() || 56 address < isolate_->heap()->old_space()->limit()) { 57 return; 58 } 59 60 for (Page* page : *isolate_->heap()->old_space()) { 61 if (CheckPage(address, page)) { 62 return; 63 } 64 } 65 66 for (LargePage* page : *isolate_->heap()->lo_space()) { 67 if (address >= page->area_start() && address < page->area_end()) { 68 Object ptr = page->GetObject(); 69 FullObjectSlot root = FullObjectSlot(&ptr); 70 delegate_->VisitRootPointer(Root::kHandleScope, nullptr, root); 71 DCHECK(root == FullObjectSlot(&ptr)); 72 return; 73 } 74 } 75} 76 77} // namespace internal 78} // namespace v8 79