1 /* Cycript - Optimizing JavaScript Compiler/Runtime
 
   2  * Copyright (C) 2009-2014  Jay Freeman (saurik)
 
   5 /* GNU Affero General Public License, Version 3 {{{ */
 
   7  * This program is free software: you can redistribute it and/or modify
 
   8  * it under the terms of the GNU Affero General Public License as published by
 
   9  * the Free Software Foundation, either version 3 of the License, or
 
  10  * (at your option) any later version.
 
  12  * This program is distributed in the hope that it will be useful,
 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15  * GNU Affero General Public License for more details.
 
  17  * You should have received a copy of the GNU Affero General Public License
 
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
  22 #ifndef CYCRIPT_POOLING_HPP
 
  23 #define CYCRIPT_POOLING_HPP
 
  34 #include "Exception.hpp"
 
  36 #include "Standard.hpp"
 
  39 _finline void *operator new(size_t size, CYPool &pool);
 
  40 _finline void *operator new [](size_t size, CYPool &pool);
 
  49         void (*code_)(void *);
 
  52         Cleaner(Cleaner *next, void (*code)(void *), void *data) :
 
  60     static _finline size_t align(size_t size) {
 
  61         // XXX: alignment is more complex than this
 
  62         return (size + 7) & ~0x3;
 
  65     template <typename Type_>
 
  66     static void delete_(void *data) {
 
  67         reinterpret_cast<Type_ *>(data)->~Type_();
 
  70     CYPool(const CYPool &);
 
  81         for (Cleaner *cleaner(cleaner_); cleaner != NULL; ) {
 
  82             Cleaner *next(cleaner->next_);
 
  83             (*cleaner->code_)(cleaner->data_);
 
  88     template <typename Type_>
 
  89     Type_ *malloc(size_t size) {
 
  93             // XXX: is this an optimal malloc size?
 
  94             size_ = std::max<size_t>(size, size + align(sizeof(Cleaner)));
 
  95             data_ = reinterpret_cast<uint8_t *>(::malloc(size_));
 
  97             _assert(size <= size_);
 
 103         return reinterpret_cast<Type_ *>(data);
 
 106     char *strdup(const char *data) {
 
 109         return reinterpret_cast<char *>(memdup(data, strlen(data) + 1));
 
 112     void *memdup(const void *data, size_t size) {
 
 113         void *copy(malloc<void>(size));
 
 114         memcpy(copy, data, size);
 
 118     char *strndup(const char *data, size_t size) const {
 
 119         return strmemdup(data, strnlen(data, size));
 
 122     char *strmemdup(const char *data, size_t size) const {
 
 123         char *copy(new char[size + 1]);
 
 124         memcpy(copy, data, size);
 
 129     // XXX: this could be made much more efficient
 
 130     __attribute__((__sentinel__))
 
 131     char *strcat(const char *data, ...) {
 
 132         size_t size(strlen(data)); {
 
 134             va_start(args, data);
 
 136             while (const char *arg = va_arg(args, const char *))
 
 142         char *copy(malloc<char>(size + 1)); {
 
 144             va_start(args, data);
 
 146             size_t offset(strlen(data));
 
 147             memcpy(copy, data, offset);
 
 149             while (const char *arg = va_arg(args, const char *)) {
 
 150                 size_t size(strlen(arg));
 
 151                 memcpy(copy + offset, arg, size);
 
 162     // XXX: most people using this might should use sprintf
 
 163     char *itoa(long value) {
 
 164         return sprintf(16, "%ld", value);
 
 167     __attribute__((__format__(__printf__, 3, 4)))
 
 168     char *sprintf(size_t size, const char *format, ...) {
 
 170         va_start(args, format);
 
 171         char *copy(vsprintf(size, format, args));
 
 176     char *vsprintf(size_t size, const char *format, va_list args) {
 
 180         int writ(vsnprintf(buffer, size, format, copy));
 
 184         if (size_t(writ) >= size)
 
 185             return vsprintf(writ + 1, format, args);
 
 186         return strmemdup(buffer, writ);
 
 189     void atexit(void (*code)(void *), void *data = NULL);
 
 191     template <typename Type_>
 
 193         Type_ *value(new(*this) Type_());
 
 194         atexit(&delete_<Type_>, value);
 
 199 _finline void *operator new(size_t size, CYPool &pool) {
 
 200     return pool.malloc<void>(size);
 
 203 _finline void *operator new [](size_t size, CYPool &pool) {
 
 204     return pool.malloc<void>(size);
 
 207 _finline void CYPool::atexit(void (*code)(void *), void *data) {
 
 208     cleaner_ = new(*this) Cleaner(cleaner_, code, data);
 
 220     CYData(CYPool &pool) :
 
 222         count_(_not(unsigned))
 
 229     static void *operator new(size_t size, CYPool &pool) {
 
 230         void *data(pool.malloc<void>(size));
 
 231         reinterpret_cast<CYData *>(data)->pool_ = &pool;
 
 235     static void *operator new(size_t size) {
 
 236         return operator new(size, *new CYPool());
 
 239     static void operator delete(void *data) {
 
 240         delete reinterpret_cast<CYData *>(data)->pool_;
 
 244 template <typename Type_>
 
 245 struct CYPoolAllocator {
 
 248     typedef Type_ value_type;
 
 249     typedef value_type *pointer;
 
 250     typedef const value_type *const_pointer;
 
 251     typedef value_type &reference;
 
 252     typedef const value_type &const_reference;
 
 253     typedef std::size_t size_type;
 
 254     typedef std::ptrdiff_t difference_type;
 
 261     template <typename Right_>
 
 262     CYPoolAllocator(const CYPoolAllocator<Right_> &rhs) :
 
 267     pointer allocate(size_type size, const void *hint = 0) {
 
 268         return pool_->malloc<value_type>(size);
 
 271     void deallocate(pointer data, size_type size) {
 
 274     void construct(pointer address, const Type_ &rhs) {
 
 275         new(address) Type_(rhs);
 
 278     void destroy(pointer address) {
 
 282     template <typename Right_>
 
 283     inline bool operator==(const CYPoolAllocator<Right_> &rhs) {
 
 284         return pool_ == rhs.pool_;
 
 287     template <typename Right_>
 
 288     inline bool operator!=(const CYPoolAllocator<Right_> &rhs) {
 
 289         return !operator==(rhs);
 
 292     template <typename Right_>
 
 294         typedef CYPoolAllocator<Right_> other;
 
 302     CYLocal<CYPool> local_;
 
 313     (*CYLocal<CYPool>::Get())
 
 316 ::pthread_key_t CYLocal<CYPool>::key_;
 
 318 #endif/*CYCRIPT_POOLING_HPP*/