// Copyright 2019 The Chromium Authors
// 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<char*>(ptr) - reinterpret_cast<char*>(fromspace());
auto* new_ptr = reinterpret_cast<char*>(tospace()) + offset;
return reinterpret_cast<HeapAddress>(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<void*>(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<ReturnAddress>(*(fp + 1));
// Step up into the caller's frame or bail if we're at the top of stack
fp = reinterpret_cast<FramePtr>(*fp);
if (reinterpret_cast<uintptr_t>(fp) == TopOfStack)
break;
printf("==== Frame %p ====\n", reinterpret_cast<void*>(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<uintptr_t*>((fp - offset));
printf("\tRoot: [RBP - %d]\n", root);
printf("\tAddress: %p\n", reinterpret_cast<void*>(*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<HeapObject*>(*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<HeapAddress>(*stack_address));
*stack_address = reinterpret_cast<uintptr_t>(new_ptr);
printf("\tAddress after Relocation: %p\n",
reinterpret_cast<void*>(*stack_address));
}
}
}
heap->MoveObjects();
}
Handle<HeapObject> AllocateHeapObject(long data) {
HeapAddress ptr = heap->AllocRaw(data);
return Handle<HeapObject>::New(reinterpret_cast<HeapObject*>(ptr));
}
void InitGC() {
InitTopOfStack();
heap = new Heap();
}
void TeardownGC() {
delete heap;
}
void PrintSafepointTable() {
spt.Print();
}