Index: src/examples/gc_no_raii/src/internal/collector.h
===================================================================
--- src/examples/gc_no_raii/src/internal/collector.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
+++ src/examples/gc_no_raii/src/internal/collector.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tools.h"
+
+#include "gcpointers.h"
+#include "internal/collector.h"
+#include "internal/gc_tools.h"
+#include "internal/globals.h"
+#include "internal/object_header.h"
+#include "internal/state.h"
+
+typedef int worklist_t;
+
+inline bool gc_is_managed(void* address)
+{
+	return gc_is_in_heap(gc_get_state(), address);
+}
+
+inline struct gc_object_header* gc_get_object_ptr(void* ptr)
+{
+	void* clean = gc_get_aligned_ptr(ptr);
+	return ((struct gc_object_header*)clean) - 1;
+}
+
+inline struct gc_memory_pool* pool_of(void* address)
+{
+	return (struct gc_memory_pool*)(((intptr_t)address) & POOL_PTR_MASK);
+}
+
+inline void gc_conditional_collect()
+{
+	if(gc_needs_collect(gc_get_state()))
+	{
+		gc_collect(gc_get_state());
+	}
+}
+
+gcpointer_t** gc_find_previous_ref(gcpointer_t* target);
+
+void* gc_allocate(size_t size);
+
+void gc_process_reference(void** ref, worklist_t* worklist);
+
+struct gc_object_header* gc_copy_object(struct gc_object_header* ptr);
+
+void gc_scan_object(struct gc_object_header* object, worklist_t* worklist);
Index: src/examples/gc_no_raii/src/internal/gc_tools.h
===================================================================
--- src/examples/gc_no_raii/src/internal/gc_tools.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
+++ src/examples/gc_no_raii/src/internal/gc_tools.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tools.h"
+#include "globals.h"
+
+inline bool gc_is_aligned(void* address)
+{
+	return (((intptr_t)address) & (~OBJECT_PTR_MASK)) == 0;
+}
+
+inline void* gc_get_aligned_ptr(void* address)
+{
+	return (void*)(((intptr_t)address) & (OBJECT_PTR_MASK));
+}
+
+inline void* gc_write_aligned_ptr(void** reference, void* address)
+{
+	size_t ref_last_bits = ((intptr_t)*reference) & (~OBJECT_PTR_MASK);
+
+      size_t new_val = ((intptr_t)address) & OBJECT_PTR_MASK;
+
+      (*reference) = (void*)(new_val | ref_last_bits);
+
+	return *reference;
+}
+
+inline size_t gc_compute_size(size_t size)
+{
+	size_t word_size = ((size - 1) / OBJECT_ALLIGNMENT) + 1;
+	size_t ret = word_size * OBJECT_ALLIGNMENT;
+
+	check(ret >= size);
+	check((ret % OBJECT_ALLIGNMENT) == 0);
+	check( ((size % OBJECT_ALLIGNMENT) != 0) || (ret == size) );
+
+	return ret;
+}
Index: src/examples/gc_no_raii/src/internal/globals.h
===================================================================
--- src/examples/gc_no_raii/src/internal/globals.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
+++ src/examples/gc_no_raii/src/internal/globals.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+static const size_t POOL_SIZE_EXP = 24;
+static const size_t POOL_SIZE_BYTES = 0x1 << POOL_SIZE_EXP;
+static const size_t POOL_PTR_MASK = ~(POOL_SIZE_BYTES - 1);
+
+static const size_t CARDS_SIZE_EXP = 12;
+static const size_t CARDS_SIZE_BYTES = 0x1 << CARDS_SIZE_EXP;
+static const size_t CARDS_OFFSET_MASK = (~(CARDS_SIZE_BYTES - 1)) & (POOL_SIZE_BYTES - 1);
+static const size_t CARDS_COUNT = POOL_SIZE_BYTES / CARDS_SIZE_BYTES;
+
+static const size_t OBJECT_ALLIGNMENT = sizeof(size_t);
+static const size_t OBJECT_PTR_MASK = ~(OBJECT_ALLIGNMENT - 1);
Index: src/examples/gc_no_raii/src/internal/object_header.h
===================================================================
--- src/examples/gc_no_raii/src/internal/object_header.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
+++ src/examples/gc_no_raii/src/internal/object_header.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tools.h"
+
+static const void* CANARY_VALUE = (void*)0xCAFEBABACAFEBABA;
+
+struct gcpointer_t;
+
+struct gc_object_header
+{
+	#if _DEBUG
+		void* canary_start;
+	#endif
+
+	size_t				size;
+	gcpointer_t* 			root_chain;
+	gcpointer_t*			type_chain;
+	struct gc_object_header*	forward;
+	bool					is_forwarded;
+
+	#if _DEBUG
+		void* canary_end;
+	#endif
+};
Index: src/examples/gc_no_raii/src/internal/state.c
===================================================================
--- src/examples/gc_no_raii/src/internal/state.c	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
+++ src/examples/gc_no_raii/src/internal/state.c	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
@@ -0,0 +1,276 @@
+#include "state.hpp"
+
+#include <algorithm>
+#include <iostream>
+
+//general purpouse includes
+#include "tools.hpp"
+
+//platform abstraction includes
+#include "allocate-pool.h"
+
+//gc internal includes
+#include "globals.hpp"
+#include "memory_pool.hpp"
+#include "memory_pool_iterator.hpp"
+#include "object_header.hpp"
+
+void swap(gc_state* state);
+void sweep_roots(worklist_t worklist);
+void clear(gc_state* state);
+void calc_usage(gc_state* state);
+
+#if DEBUG
+	bool roots_match(gc_state* state);
+	bool no_from_space_ref(gc_state* state);
+#endif
+
+void gc_state_ctor(gc_state* state)
+{
+	state->from_code(0)
+	state->to_space(nullptr)
+	state->from_space(nullptr)
+	state->total_space(0)
+	state->used_space(0)
+	state->pools_table()
+
+	gc_allocate_pool(gc_state* state);
+}
+
+bool state::is_in_heap(void* address) const
+{
+	memory_pool* target_pool = pool_of(address);
+
+	auto first = pools_table.cbegin();
+	auto last = pools_table.cend();
+	auto result = std::find(first, last, target_pool);
+	return result != last && (*result)->is_from_space();
+}
+
+bool state::is_in_to_space(void* address) const
+{
+	const memory_pool* target_pool = pool_of(address);
+
+	auto first = pools_table.cbegin();
+	auto last = pools_table.cend();
+	auto result = std::find(first, last, target_pool);
+	return result != last && !(*result)->is_from_space();
+}
+
+object_header* state::get_object_for_ref(void* member)
+{
+	intptr_t target = intptr_t(member);
+	if(!is_in_heap(member)) return nullptr;
+
+	memory_pool* pool = pool_of(member);
+	auto it = pool->iterator_for(member);
+	auto end = pool->end();
+
+	while(it != end)
+	{
+		object_header* object = *it;
+		{
+			intptr_t start = intptr_t(object);
+			intptr_t end = intptr_t(start + object->size);
+			if(start < target && end > target)
+			{
+				return object;
+			}
+		}
+		++it;
+	}
+
+	checkf(false, "is_in_heap() and iterator_for() return inconsistent data");
+	abort();
+	return nullptr;
+}
+
+void* state::try_allocate(size_t size)
+{
+	memory_pool* pool = from_space;
+	while(pool)
+	{
+		if(pool->size_left() > size)
+		{
+			return pool->allocate(size, true);
+		}
+		pool = pool->next();
+	}
+
+	return nullptr;
+}
+
+void state::allocate_pool()
+{
+	memory_pool* old_from_space = from_space;
+      memory_pool* old_to_space = to_space;
+
+      from_space = reinterpret_cast<memory_pool*>(pal_allocPool(POOL_SIZE_BYTES, 1));
+      to_space = reinterpret_cast<memory_pool*>(pal_allocPool(POOL_SIZE_BYTES, 1));
+
+      new (from_space) memory_pool(POOL_SIZE_BYTES, old_from_space, to_space, from_code);
+      new (to_space) memory_pool(POOL_SIZE_BYTES, old_to_space, from_space, (~from_code) & 0x01);
+
+	total_space += from_space->size();
+
+	pools_table.push_back(from_space);
+	pools_table.push_back(to_space);
+}
+
+void state::collect()
+{
+	DEBUG("collecting");
+	DEBUG("previous usage " << used_space << " / " << total_space);
+
+	std::vector<void**> worklist;
+	sweep_roots(worklist);
+
+	while(!worklist.empty())
+	{
+		void** ref = worklist.back();
+		worklist.pop_back();
+		process_reference(ref, worklist);
+	}
+
+	check(roots_match());
+	check(no_from_space_ref());
+
+	swap();
+
+	calc_usage();
+
+	if(needs_collect()) allocate_pool();
+
+	DEBUG("done");
+}
+
+void state::swap()
+{
+	std::swap(from_space, to_space);
+
+	memory_pool* pool = to_space;
+	while(pool)
+	{
+		pool->reset();
+		pool = pool->next();
+	}
+
+	from_code = (~from_code) & 0x01;
+
+	#if _DEBUG
+		{
+			memory_pool* pool = from_space;
+			while(pool)
+			{
+				check(pool->is_from_space());
+				pool = pool->next();
+			}
+
+			pool = to_space;
+			while(pool)
+			{
+				check(!pool->is_from_space());
+				pool = pool->next();
+			}
+		}
+	#endif
+}
+
+void state::sweep_roots(std::vector<void**>& worklist)
+{
+	memory_pool* pool = from_space;
+	while(pool)
+	{
+		for(object_header* object : *pool)
+		{
+			if(!object->root_chain) continue;
+
+			copy_object(object);
+
+			scan_object(object->forward, worklist);
+		}
+
+		pool = pool->next();
+	}
+}
+
+void state::clear()
+{
+	memory_pool* pool = from_space;
+	while(pool)
+	{
+		pool->reset();
+		pool = pool->next();
+	}
+
+	pool = to_space;
+	while(pool)
+	{
+		pool->reset();
+		pool = pool->next();
+	}
+}
+
+void state::calc_usage()
+{
+	total_space = 0;
+	used_space = 0;
+
+	memory_pool* pool = from_space;
+	while(pool)
+	{
+		size_t size = pool->size();
+		size_t used = size - pool->size_left();
+		check(used <= size);
+		total_space += size;
+		used_space += used;
+
+		pool = pool->next();
+	}
+}
+
+#if _DEBUG
+	bool state::roots_match()
+	{
+		memory_pool* pool = to_space;
+		while(pool)
+		{
+			size_t size = 0;
+			for(object_header* object : *pool)
+			{
+				size += object->size;
+
+				gcpointer_base* ptr = object->root_chain;
+				while(ptr)
+				{
+					check(get_object_ptr(ptr->m_ptr) == object);
+					ptr = ptr->m_next;
+				}
+			}
+
+			check(size + pool->size_left() == pool->size());
+
+			pool = pool->next();
+		}
+
+		return true;
+	}
+
+	bool state::no_from_space_ref()
+	{
+		memory_pool* pool = to_space;
+		while(pool)
+		{
+			void** potential_ref = (void**)pool->m_start;
+			while(potential_ref < (void**)pool->m_free)
+			{
+				check(!is_in_heap(*potential_ref));
+				potential_ref++;
+			}
+
+			pool = pool->next();
+		}
+
+		return true;
+	}
+#endif
Index: src/examples/gc_no_raii/src/internal/state.h
===================================================================
--- src/examples/gc_no_raii/src/internal/state.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
+++ src/examples/gc_no_raii/src/internal/state.h	(revision a2b2761456045c52741a58f2397c74bcfbf3c113)
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "tools.h"
+
+struct gc_state
+{
+	bool is_initialized;
+	uint8_t from_code;
+	struct gc_memory_pool* to_space;
+	struct gc_memory_pool* from_space;
+
+	size_t total_space;
+	size_t used_space;
+
+	const struct memory_pool* 	pools_table;
+	size_t 				pools_table_count;
+};
+
+void gc_state_ctor(gc_state* state);
+
+inline gc_state* get_state()
+{
+	static gc_state s;
+	if(!s.is_initialized) gc_state_ctor(s);
+	return &s;
+}
+
+inline bool needs_collect(gc_state* state)
+{
+	return state->used_space * 2 > state->total_space;
+}
+
+void gc_collect(gc_state* state);
+
+void* gc_try_allocate(gc_state* state, size_t size);
+
+void gc_allocate_pool(gc_state* state);
+
+bool gc_is_in_heap(const gc_state* state, void* address);
+
+bool gc_is_in_to_space(const gc_state* state, void* address);
+
+inline uint8_t gc_from_space_code(const gc_state* state)
+{
+	return state->from_code;
+}
+
+struct gc_object_header* gc_get_object_for_ref(gc_state* state, void*);
+
+inline void gc_register_allocation(gc_state* state, size_t size)
+{
+	state->used_space += size;
+}
