MichaReiser/speedy.js

View on GitHub
packages/runtime/lib/memory.cc

Summary

Maintainability
Test Coverage
//
// Created by Micha Reiser on 04.04.17.
//

#include <cstdlib>
#include <array>
#include <cassert>
#include "macros.h"

struct CollectedPointers {
    std::array<void*, 10000> pointers;
    size_t count;

    CollectedPointers() : pointers {}, count {}
    {}
};

extern "C" {

extern void malloc_inspect_all(void(*handler)(void*, void *, size_t, void*), void* arg);
extern size_t bulk_free(void**, size_t n_elements);

ALWAYS_INLINE void collectPointers(void* start, void*, size_t used_bytes, void* callback_arg) {
    auto collectedPointers = static_cast<CollectedPointers*>(callback_arg);

    if (used_bytes > 0 && collectedPointers->count < collectedPointers->pointers.size()) {
        collectedPointers->pointers[collectedPointers->count++] = start;
    }
}

/**
 * Collects all allocated data and calls free. Does not invoke destructors!
 * The helper struct is used as we should not use any heap allocation in this method (otherwise we nuke our own data!)
 */
DLL_PUBLIC ALWAYS_INLINE void speedyJsGc() {
    CollectedPointers collectedPointers {};
    do {
        collectedPointers.count = 0;

        malloc_inspect_all(collectPointers, &collectedPointers);
        auto released = bulk_free(collectedPointers.pointers.data(), collectedPointers.count);
        assert(released == 0 && "Not all pointers freed by bulk_free");
    } while (collectedPointers.count >= collectedPointers.pointers.size());
}

// Probably malloc can be overriden and use emscripten_builtin_malloc to have a custom malloc version
// extern __typeof(malloc) emscripten_builtin_malloc __attribute__((weak, alias("malloc")));
// extern __typeof(free) emscripten_builtin_free __attribute__((weak, alias("free")));
}