// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "gc_api.h" SafepointTable spt = GenSafepointTable(); Heap* heap = nullptr; HeapAddress Heap::AllocRaw(long value) { assert(heap_ptr < kHeapSize && "Allocation failed: Heap full"); HeapAddress raw_ptr = &fromspace()[heap_ptr]; *raw_ptr = value; heap_ptr++; return raw_ptr; } void Heap::MoveObjects() { for (int i = 0; i < kHeapSize; i++) { auto tmp = a_frag_[i]; a_frag_[i] = b_frag_[i]; b_frag_[i] = tmp; } alloc_on_a_ = !alloc_on_a_; } HeapAddress Heap::UpdatePointer(HeapAddress ptr) { int offset = reinterpret_cast(ptr) - reinterpret_cast(fromspace()); auto* new_ptr = reinterpret_cast(tospace()) + offset; return reinterpret_cast(new_ptr); } void FrameRoots::Print() const { printf("\tRegister Roots: NYI\n"); if (!stack_roots_.size()) { printf("\tStack Roots: []\n"); return; } printf("\tStack Roots: ["); for (auto SR : stack_roots_) { printf("RBP - %d, ", SR); } printf("\b\b]\n"); } void SafepointTable::Print() const { printf("Safepoint Table\n"); for (auto const& pair : roots_) { printf("Frame %p\n", reinterpret_cast(pair.first)); pair.second.Print(); } } extern "C" void StackWalkAndMoveObjects(FramePtr fp) { while (true) { // The caller's return address is always 1 machine word above the recorded // RBP value in the current frame auto ra = reinterpret_cast(*(fp + 1)); // Step up into the caller's frame or bail if we're at the top of stack fp = reinterpret_cast(*fp); if (reinterpret_cast(fp) == TopOfStack) break; printf("==== Frame %p ====\n", reinterpret_cast(ra)); auto it = spt.roots()->find(ra); if (it != spt.roots()->end()) { auto fr_roots = it->second; for (auto root : *fr_roots.stack_roots()) { auto offset = root / sizeof(uintptr_t); auto stack_address = reinterpret_cast((fp - offset)); printf("\tRoot: [RBP - %d]\n", root); printf("\tAddress: %p\n", reinterpret_cast(*stack_address)); // We know that all HeapObjects are wrappers around a single long // integer, so for debugging purposes we can cast it as such and print // the value to see if it looks correct. printf("\tValue: %ld\n", reinterpret_cast(*stack_address)->data); // We are in a collection, so we know that the underlying objects will // be moved before we return to the mutator. We update the on-stack // pointers here to point to the object's new location in the heap. HeapAddress new_ptr = heap->UpdatePointer(reinterpret_cast(*stack_address)); *stack_address = reinterpret_cast(new_ptr); printf("\tAddress after Relocation: %p\n", reinterpret_cast(*stack_address)); } } } heap->MoveObjects(); } Handle AllocateHeapObject(long data) { HeapAddress ptr = heap->AllocRaw(data); return Handle::New(reinterpret_cast(ptr)); } void InitGC() { InitTopOfStack(); heap = new Heap(); } void TeardownGC() { delete heap; } void PrintSafepointTable() { spt.Print(); }