aboutsummaryrefslogtreecommitdiff
path: root/src/mem.hpp
diff options
context:
space:
mode:
authorMichael Dusan <michael.dusan@gmail.com>2020-02-10 21:08:08 -0500
committerMichael Dusan <michael.dusan@gmail.com>2020-02-10 21:08:08 -0500
commitedb210905dcbe666fa5222bceacd2e5bdb16bb89 (patch)
tree984aec0e5bad756daf426855c54bae3c42c73eca /src/mem.hpp
parent1cdefeb10b7496126bbb7d00709235abfee56a4a (diff)
downloadzig-edb210905dcbe666fa5222bceacd2e5bdb16bb89.tar.gz
zig-edb210905dcbe666fa5222bceacd2e5bdb16bb89.zip
stage1: memory/report overhaul
- split util_base.hpp from util.hpp - new namespaces: `mem` and `heap` - new `mem::Allocator` interface - new `heap::CAllocator` impl with global `heap::c_allocator` - new `heap::ArenaAllocator` impl - new `mem::TypeInfo` extracts names without RTTI - name extraction is enabled w/ ZIG_ENABLE_MEM_PROFILE=1 - new `mem::List` takes explicit `Allocator&` parameter - new `mem::HashMap` takes explicit `Allocator&` parameter - add Codegen.pass1_arena and use for all `ZigValue` allocs - deinit Codegen.pass1_arena early in `zig_llvm_emit_output()`
Diffstat (limited to 'src/mem.hpp')
-rw-r--r--src/mem.hpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/mem.hpp b/src/mem.hpp
new file mode 100644
index 0000000000..9e262b7d53
--- /dev/null
+++ b/src/mem.hpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_MEM_HPP
+#define ZIG_MEM_HPP
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "util_base.hpp"
+#include "mem_type_info.hpp"
+
+//
+// -- Memory Allocation General Notes --
+//
+// `heap::c_allocator` is the preferred general allocator.
+//
+// `heap::bootstrap_allocator` is an implementation detail for use
+// by allocators themselves when incidental heap may be required for
+// profiling and statistics. It breaks the infinite recursion cycle.
+//
+// `mem::os` contains a raw wrapper for system malloc API used in
+// preference to calling ::{malloc, free, calloc, realloc} directly.
+// This isolates usage and helps with audits:
+//
+// mem::os::malloc
+// mem::os::free
+// mem::os::calloc
+// mem::os::realloc
+//
+namespace mem {
+
+// initialize mem module before any use
+void init();
+
+// deinitialize mem module to free memory and print report
+void deinit();
+
+// isolate system/libc allocators
+namespace os {
+
+ATTRIBUTE_RETURNS_NOALIAS
+inline void *malloc(size_t size) {
+#ifndef NDEBUG
+ // make behavior when size == 0 portable
+ if (size == 0)
+ return nullptr;
+#endif
+ auto ptr = ::malloc(size);
+ if (ptr == nullptr)
+ zig_panic("allocation failed");
+ return ptr;
+}
+
+inline void free(void *ptr) {
+ ::free(ptr);
+}
+
+ATTRIBUTE_RETURNS_NOALIAS
+inline void *calloc(size_t count, size_t size) {
+#ifndef NDEBUG
+ // make behavior when size == 0 portable
+ if (count == 0 || size == 0)
+ return nullptr;
+#endif
+ auto ptr = ::calloc(count, size);
+ if (ptr == nullptr)
+ zig_panic("allocation failed");
+ return ptr;
+}
+
+inline void *realloc(void *old_ptr, size_t size) {
+#ifndef NDEBUG
+ // make behavior when size == 0 portable
+ if (old_ptr == nullptr && size == 0)
+ return nullptr;
+#endif
+ auto ptr = ::realloc(old_ptr, size);
+ if (ptr == nullptr)
+ zig_panic("allocation failed");
+ return ptr;
+}
+
+} // namespace os
+
+struct Allocator {
+ virtual void destruct(Allocator *allocator) = 0;
+
+ template <typename T> ATTRIBUTE_RETURNS_NOALIAS
+ T *allocate(size_t count) {
+ return reinterpret_cast<T *>(this->internal_allocate(TypeInfo::make<T>(), count));
+ }
+
+ template <typename T> ATTRIBUTE_RETURNS_NOALIAS
+ T *allocate_nonzero(size_t count) {
+ return reinterpret_cast<T *>(this->internal_allocate_nonzero(TypeInfo::make<T>(), count));
+ }
+
+ template <typename T>
+ T *reallocate(T *old_ptr, size_t old_count, size_t new_count) {
+ return reinterpret_cast<T *>(this->internal_reallocate(TypeInfo::make<T>(), old_ptr, old_count, new_count));
+ }
+
+ template <typename T>
+ T *reallocate_nonzero(T *old_ptr, size_t old_count, size_t new_count) {
+ return reinterpret_cast<T *>(this->internal_reallocate_nonzero(TypeInfo::make<T>(), old_ptr, old_count, new_count));
+ }
+
+ template<typename T>
+ void deallocate(T *ptr, size_t count) {
+ this->internal_deallocate(TypeInfo::make<T>(), ptr, count);
+ }
+
+ template<typename T>
+ T *create() {
+ return reinterpret_cast<T *>(this->internal_allocate(TypeInfo::make<T>(), 1));
+ }
+
+ template<typename T>
+ void destroy(T *ptr) {
+ this->internal_deallocate(TypeInfo::make<T>(), ptr, 1);
+ }
+
+protected:
+ ATTRIBUTE_RETURNS_NOALIAS virtual void *internal_allocate(const TypeInfo &info, size_t count) = 0;
+ ATTRIBUTE_RETURNS_NOALIAS virtual void *internal_allocate_nonzero(const TypeInfo &info, size_t count) = 0;
+ virtual void *internal_reallocate(const TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) = 0;
+ virtual void *internal_reallocate_nonzero(const TypeInfo &info, void *old_ptr, size_t old_count, size_t new_count) = 0;
+ virtual void internal_deallocate(const TypeInfo &info, void *ptr, size_t count) = 0;
+};
+
+#ifdef ZIG_ENABLE_MEM_PROFILE
+void print_report(FILE *file = nullptr);
+
+// global memory report flag
+extern bool report_print;
+// global memory report default destination
+extern FILE *report_file;
+#endif
+
+} // namespace mem
+
+#endif