diff --git a/source/lib/allocators/pool.cpp b/source/lib/allocators/pool.cpp index 85d651c816..f95840a26e 100644 --- a/source/lib/allocators/pool.cpp +++ b/source/lib/allocators/pool.cpp @@ -70,11 +70,15 @@ void* pool_alloc(Pool* p, size_t size) // otherwise the pool el_size setting. const size_t el_size = p->el_size? p->el_size : mem_RoundUpToAlignment(size); + void* el; // note: this can never happen in pools with variable-sized elements // because they disallow pool_free. - void* el = mem_freelist_Detach(p->freelist); - if(el) - goto have_el; + if (p->freelist) + { + el = mem_freelist_Detach(p->freelist); + if(el) + goto have_el; + } // alloc a new entry { diff --git a/source/lib/allocators/pool.h b/source/lib/allocators/pool.h index 5a3150a49b..8f1e869fbd 100644 --- a/source/lib/allocators/pool.h +++ b/source/lib/allocators/pool.h @@ -172,6 +172,134 @@ private: Pool m_pool; }; -#endif +/** + * C++ wrapper on top of pool_alloc for variable-sized allocations. + * Memory is returned uninitialised. + */ +class RawPoolAllocator +{ +public: + /** + * @param maxSize maximum size of pool in bytes + */ + explicit RawPoolAllocator(size_t maxSize) + { + (void)pool_create(&m_pool, maxSize, 0); + } + + ~RawPoolAllocator() + { + (void)pool_destroy(&m_pool); + } + + /** + * @param count number of elements of type T to allocate space for + */ + template + T* AllocateMemory(size_t count) + { + T* t = (T*)pool_alloc(&m_pool, count*sizeof(T)); + if(!t) + throw std::bad_alloc(); + return t; + } + +private: + Pool m_pool; +}; + +/** + * STL-compatible allocator based on a RawPoolAllocator. + * (Allocated memory is never freed, until the RawPoolAllocator is destroyed.) + */ +template +class pool_allocator +{ +private: + // No default constructor + pool_allocator() throw (); + +public: + RawPoolAllocator& p; + + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + template + struct rebind + { + typedef pool_allocator other; + }; + + explicit pool_allocator(RawPoolAllocator& pool) throw () : + p(pool) + { + } + + template + pool_allocator(const pool_allocator& alloc) throw () : + p(alloc.p) + { + } + + pointer address(reference r) + { + return &r; + } + + const_pointer address(const_reference s) + { + return &s; + } + + size_type max_size() const throw () + { + return std::numeric_limits::max() / sizeof(T); + } + + void construct(const pointer ptr, const value_type& t) + { + new (ptr) T(t); + } + + void destroy(const pointer ptr) + { + ptr->~T(); + } + + pointer allocate(size_type n) + { + return p.AllocateMemory (n); + } + + pointer allocate(size_type n, const void* const) + { + return allocate(n); + } + + void deallocate(const pointer UNUSED(ptr), const size_type UNUSED(n)) + { + // ignore deallocations + } +}; + +template +bool operator==(const pool_allocator&, const pool_allocator&) throw () +{ + return true; +} + +template +bool operator!=(const pool_allocator&, const pool_allocator&) throw () +{ + return false; +} + +#endif // __cplusplus #endif // #ifndef INCLUDED_POOL diff --git a/source/simulation2/helpers/Grid.h b/source/simulation2/helpers/Grid.h index 3496706856..d13a0fbfa9 100644 --- a/source/simulation2/helpers/Grid.h +++ b/source/simulation2/helpers/Grid.h @@ -18,6 +18,8 @@ #ifndef INCLUDED_GRID #define INCLUDED_GRID +#include + #ifdef NDEBUG #define GRID_BOUNDS_DEBUG 0 #else diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp index 8115f19949..109c6c77af 100644 --- a/source/simulation2/serialization/BinarySerializer.cpp +++ b/source/simulation2/serialization/BinarySerializer.cpp @@ -24,7 +24,6 @@ #include "ps/CLogger.h" #include "scriptinterface/ScriptInterface.h" -#include "scriptinterface/AutoRooters.h" // Shut up some warnings triggered by jsobj.h #if MSC_VERSION @@ -40,7 +39,8 @@ #endif CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(ScriptInterface& scriptInterface, ISerializer& serializer) : - m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_ScriptBackrefsNext(1), m_Rooter(m_ScriptInterface) + m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_Rooter(m_ScriptInterface), + m_ScriptBackrefsPool(1*MiB), m_ScriptBackrefs(backrefs_t::key_compare(), ScriptBackrefsAlloc(m_ScriptBackrefsPool)), m_ScriptBackrefsNext(1) { } diff --git a/source/simulation2/serialization/BinarySerializer.h b/source/simulation2/serialization/BinarySerializer.h index cc10702270..07b52732ef 100644 --- a/source/simulation2/serialization/BinarySerializer.h +++ b/source/simulation2/serialization/BinarySerializer.h @@ -23,6 +23,7 @@ #include "scriptinterface/AutoRooters.h" #include "lib/byte_order.h" +#include "lib/allocators/pool.h" #include @@ -41,8 +42,11 @@ private: ScriptInterface& m_ScriptInterface; ISerializer& m_Serializer; - typedef std::map backrefs_t; + // Pooling helps since we do a lot of short-lived allocations + typedef pool_allocator > ScriptBackrefsAlloc; + typedef std::map, ScriptBackrefsAlloc> backrefs_t; + RawPoolAllocator m_ScriptBackrefsPool; backrefs_t m_ScriptBackrefs; u32 m_ScriptBackrefsNext; u32 GetScriptBackrefTag(JSObject* obj); diff --git a/source/simulation2/serialization/IDeserializer.h b/source/simulation2/serialization/IDeserializer.h index 10e38fa55e..88f2b0f40a 100644 --- a/source/simulation2/serialization/IDeserializer.h +++ b/source/simulation2/serialization/IDeserializer.h @@ -20,7 +20,6 @@ #include "maths/Fixed.h" #include "ps/Errors.h" -#include "ps/utf16string.h" #include "scriptinterface/ScriptTypes.h" ERROR_GROUP(Deserialize); diff --git a/source/simulation2/serialization/StdDeserializer.cpp b/source/simulation2/serialization/StdDeserializer.cpp index 2904d6e5fd..0fe125517a 100644 --- a/source/simulation2/serialization/StdDeserializer.cpp +++ b/source/simulation2/serialization/StdDeserializer.cpp @@ -22,6 +22,7 @@ #include "SerializedScriptTypes.h" #include "scriptinterface/ScriptInterface.h" + #include "js/jsapi.h" CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) : diff --git a/source/simulation2/serialization/StdDeserializer.h b/source/simulation2/serialization/StdDeserializer.h index c8c94ad57a..e85f116904 100644 --- a/source/simulation2/serialization/StdDeserializer.h +++ b/source/simulation2/serialization/StdDeserializer.h @@ -20,6 +20,8 @@ #include "IDeserializer.h" +#include "ps/utf16string.h" + #include class CStdDeserializer : public IDeserializer diff --git a/source/simulation2/serialization/StdSerializer.cpp b/source/simulation2/serialization/StdSerializer.cpp index d11e4b931b..cc7cc88096 100644 --- a/source/simulation2/serialization/StdSerializer.cpp +++ b/source/simulation2/serialization/StdSerializer.cpp @@ -19,9 +19,6 @@ #include "StdSerializer.h" -#include -#include - CStdSerializerImpl::CStdSerializerImpl(std::ostream& stream) : m_Stream(stream) {