js/src/jit/IonAllocPolicy.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/IonAllocPolicy.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,222 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_IonAllocPolicy_h
    1.11 +#define jit_IonAllocPolicy_h
    1.12 +
    1.13 +#include "mozilla/GuardObjects.h"
    1.14 +#include "mozilla/TypeTraits.h"
    1.15 +
    1.16 +#include "jscntxt.h"
    1.17 +
    1.18 +#include "ds/LifoAlloc.h"
    1.19 +#include "jit/InlineList.h"
    1.20 +#include "jit/Ion.h"
    1.21 +
    1.22 +namespace js {
    1.23 +namespace jit {
    1.24 +
    1.25 +class TempAllocator
    1.26 +{
    1.27 +    LifoAllocScope lifoScope_;
    1.28 +
    1.29 +    // Linked list of GCThings rooted by this allocator.
    1.30 +    CompilerRootNode *rootList_;
    1.31 +
    1.32 +  public:
    1.33 +    TempAllocator(LifoAlloc *lifoAlloc)
    1.34 +      : lifoScope_(lifoAlloc),
    1.35 +        rootList_(nullptr)
    1.36 +    { }
    1.37 +
    1.38 +    void *allocateOrCrash(size_t bytes)
    1.39 +    {
    1.40 +        void *p = lifoScope_.alloc().alloc(bytes);
    1.41 +        if (!p)
    1.42 +            js::CrashAtUnhandlableOOM("LifoAlloc::allocOrCrash");
    1.43 +        return p;
    1.44 +    }
    1.45 +
    1.46 +    void *allocate(size_t bytes)
    1.47 +    {
    1.48 +        void *p = lifoScope_.alloc().alloc(bytes);
    1.49 +        if (!ensureBallast())
    1.50 +            return nullptr;
    1.51 +        return p;
    1.52 +    }
    1.53 +
    1.54 +    template <size_t ElemSize>
    1.55 +    void *allocateArray(size_t n)
    1.56 +    {
    1.57 +        if (n & mozilla::tl::MulOverflowMask<ElemSize>::value)
    1.58 +            return nullptr;
    1.59 +        void *p = lifoScope_.alloc().alloc(n * ElemSize);
    1.60 +        if (!ensureBallast())
    1.61 +            return nullptr;
    1.62 +        return p;
    1.63 +    }
    1.64 +
    1.65 +    LifoAlloc *lifoAlloc()
    1.66 +    {
    1.67 +        return &lifoScope_.alloc();
    1.68 +    }
    1.69 +
    1.70 +    CompilerRootNode *&rootList()
    1.71 +    {
    1.72 +        return rootList_;
    1.73 +    }
    1.74 +
    1.75 +    bool ensureBallast() {
    1.76 +        // Most infallible Ion allocations are small, so we use a ballast of
    1.77 +        // ~16K for now.
    1.78 +        return lifoScope_.alloc().ensureUnusedApproximate(16 * 1024);
    1.79 +    }
    1.80 +};
    1.81 +
    1.82 +// Stack allocated rooter for all roots associated with a TempAllocator
    1.83 +class AutoTempAllocatorRooter : private AutoGCRooter
    1.84 +{
    1.85 +  public:
    1.86 +    explicit AutoTempAllocatorRooter(JSContext *cx, TempAllocator *temp
    1.87 +                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
    1.88 +      : AutoGCRooter(cx, IONALLOC), temp(temp)
    1.89 +    {
    1.90 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
    1.91 +    }
    1.92 +
    1.93 +    friend void AutoGCRooter::trace(JSTracer *trc);
    1.94 +    void trace(JSTracer *trc);
    1.95 +
    1.96 +  private:
    1.97 +    TempAllocator *temp;
    1.98 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
    1.99 +};
   1.100 +
   1.101 +class IonAllocPolicy
   1.102 +{
   1.103 +    TempAllocator &alloc_;
   1.104 +
   1.105 +  public:
   1.106 +    IonAllocPolicy(TempAllocator &alloc)
   1.107 +      : alloc_(alloc)
   1.108 +    {}
   1.109 +    void *malloc_(size_t bytes) {
   1.110 +        return alloc_.allocate(bytes);
   1.111 +    }
   1.112 +    void *calloc_(size_t bytes) {
   1.113 +        void *p = alloc_.allocate(bytes);
   1.114 +        if (p)
   1.115 +            memset(p, 0, bytes);
   1.116 +        return p;
   1.117 +    }
   1.118 +    void *realloc_(void *p, size_t oldBytes, size_t bytes) {
   1.119 +        void *n = malloc_(bytes);
   1.120 +        if (!n)
   1.121 +            return n;
   1.122 +        memcpy(n, p, Min(oldBytes, bytes));
   1.123 +        return n;
   1.124 +    }
   1.125 +    void free_(void *p) {
   1.126 +    }
   1.127 +    void reportAllocOverflow() const {
   1.128 +    }
   1.129 +};
   1.130 +
   1.131 +// Deprecated. Don't use this. Will be removed after everything has been
   1.132 +// converted to IonAllocPolicy.
   1.133 +class OldIonAllocPolicy
   1.134 +{
   1.135 +  public:
   1.136 +    OldIonAllocPolicy()
   1.137 +    {}
   1.138 +    void *malloc_(size_t bytes) {
   1.139 +        return GetIonContext()->temp->allocate(bytes);
   1.140 +    }
   1.141 +    void *calloc_(size_t bytes) {
   1.142 +        void *p = GetIonContext()->temp->allocate(bytes);
   1.143 +        if (p)
   1.144 +            memset(p, 0, bytes);
   1.145 +        return p;
   1.146 +    }
   1.147 +    void *realloc_(void *p, size_t oldBytes, size_t bytes) {
   1.148 +        void *n = malloc_(bytes);
   1.149 +        if (!n)
   1.150 +            return n;
   1.151 +        memcpy(n, p, Min(oldBytes, bytes));
   1.152 +        return n;
   1.153 +    }
   1.154 +    void free_(void *p) {
   1.155 +    }
   1.156 +    void reportAllocOverflow() const {
   1.157 +    }
   1.158 +};
   1.159 +
   1.160 +class AutoIonContextAlloc
   1.161 +{
   1.162 +    TempAllocator tempAlloc_;
   1.163 +    IonContext *icx_;
   1.164 +    TempAllocator *prevAlloc_;
   1.165 +
   1.166 +  public:
   1.167 +    explicit AutoIonContextAlloc(JSContext *cx)
   1.168 +      : tempAlloc_(&cx->tempLifoAlloc()),
   1.169 +        icx_(GetIonContext()),
   1.170 +        prevAlloc_(icx_->temp)
   1.171 +    {
   1.172 +        icx_->temp = &tempAlloc_;
   1.173 +    }
   1.174 +
   1.175 +    ~AutoIonContextAlloc() {
   1.176 +        JS_ASSERT(icx_->temp == &tempAlloc_);
   1.177 +        icx_->temp = prevAlloc_;
   1.178 +    }
   1.179 +};
   1.180 +
   1.181 +struct TempObject
   1.182 +{
   1.183 +    inline void *operator new(size_t nbytes, TempAllocator &alloc) {
   1.184 +        return alloc.allocateOrCrash(nbytes);
   1.185 +    }
   1.186 +    template <class T>
   1.187 +    inline void *operator new(size_t nbytes, T *pos) {
   1.188 +        static_assert(mozilla::IsConvertible<T*, TempObject*>::value,
   1.189 +                      "Placement new argument type must inherit from TempObject");
   1.190 +        return pos;
   1.191 +    }
   1.192 +};
   1.193 +
   1.194 +template <typename T>
   1.195 +class TempObjectPool
   1.196 +{
   1.197 +    TempAllocator *alloc_;
   1.198 +    InlineForwardList<T> freed_;
   1.199 +
   1.200 +  public:
   1.201 +    TempObjectPool()
   1.202 +      : alloc_(nullptr)
   1.203 +    {}
   1.204 +    void setAllocator(TempAllocator &alloc) {
   1.205 +        JS_ASSERT(freed_.empty());
   1.206 +        alloc_ = &alloc;
   1.207 +    }
   1.208 +    T *allocate() {
   1.209 +        JS_ASSERT(alloc_);
   1.210 +        if (freed_.empty())
   1.211 +            return new(*alloc_) T();
   1.212 +        return freed_.popFront();
   1.213 +    }
   1.214 +    void free(T *obj) {
   1.215 +        freed_.pushFront(obj);
   1.216 +    }
   1.217 +    void clear() {
   1.218 +        freed_.clear();
   1.219 +    }
   1.220 +};
   1.221 +
   1.222 +} // namespace jit
   1.223 +} // namespace js
   1.224 +
   1.225 +#endif /* jit_IonAllocPolicy_h */

mercurial