[bmalloc] IsoHeap should have lower tier using shared IsoPage
[WebKit-https.git] / Source / bmalloc / bmalloc / IsoTLSInlines.h
index 6dbcb61..1d14b7a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #pragma once
 
+#include "Environment.h"
 #include "IsoHeapImpl.h"
 #include "IsoTLS.h"
+#include "bmalloc.h"
 
 namespace bmalloc {
 
@@ -67,7 +69,7 @@ void* IsoTLS::allocateImpl(api::IsoHeap<Type>& handle, bool abortOnFailure)
     unsigned offset = handle.allocatorOffset();
     IsoTLS* tls = get();
     if (!tls || offset >= tls->m_extent)
-        return allocateSlow<typename api::IsoHeap<Type>::Config>(handle, abortOnFailure);
+        return allocateSlow<Config>(handle, abortOnFailure);
     return tls->allocateFast<Config>(offset, abortOnFailure);
 }
 
@@ -80,14 +82,25 @@ void* IsoTLS::allocateFast(unsigned offset, bool abortOnFailure)
 template<typename Config, typename Type>
 BNO_INLINE void* IsoTLS::allocateSlow(api::IsoHeap<Type>& handle, bool abortOnFailure)
 {
-    IsoTLS* tls = ensureHeapAndEntries(handle);
+    for (;;) {
+        switch (s_mallocFallbackState) {
+        case MallocFallbackState::Undecided:
+            determineMallocFallbackState();
+            continue;
+        case MallocFallbackState::FallBackToMalloc:
+            return api::tryMalloc(Config::objectSize);
+        case MallocFallbackState::DoNotFallBack:
+            break;
+        }
+        break;
+    }
     
-    auto debugMallocResult = debugMalloc(Config::objectSize);
-    if (debugMallocResult.usingDebugHeap)
-        return debugMallocResult.ptr;
+    // If debug heap is enabled, s_mallocFallbackState becomes MallocFallbackState::FallBackToMalloc.
+    BASSERT(!Environment::get()->isDebugHeapEnabled());
     
-    unsigned offset = handle.allocatorOffset();
-    return tls->allocateFast<Config>(offset, abortOnFailure);
+    IsoTLS* tls = ensureHeapAndEntries(handle);
+    
+    return tls->allocateFast<Config>(handle.allocatorOffset(), abortOnFailure);
 }
 
 template<typename Config, typename Type>
@@ -97,16 +110,42 @@ void IsoTLS::deallocateImpl(api::IsoHeap<Type>& handle, void* p)
     IsoTLS* tls = get();
     // Note that this bounds check would be here even if we didn't have to support DebugHeap,
     // since we don't want unpredictable behavior if offset or m_extent ever got corrupted.
-    if (offset >= tls->m_extent)
-        deallocateSlow(p);
+    if (!tls || offset >= tls->m_extent)
+        deallocateSlow<Config>(handle, p);
     else
-        tls->deallocateFast<Config>(offset, p);
+        tls->deallocateFast<Config>(handle, offset, p);
 }
 
-template<typename Config>
-void IsoTLS::deallocateFast(unsigned offset, void* p)
+template<typename Config, typename Type>
+void IsoTLS::deallocateFast(api::IsoHeap<Type>& handle, unsigned offset, void* p)
 {
-    reinterpret_cast<IsoDeallocator<Config>*>(m_data + offset)->deallocate(p);
+    reinterpret_cast<IsoDeallocator<Config>*>(m_data + offset)->deallocate(handle, p);
+}
+
+template<typename Config, typename Type>
+BNO_INLINE void IsoTLS::deallocateSlow(api::IsoHeap<Type>& handle, void* p)
+{
+    for (;;) {
+        switch (s_mallocFallbackState) {
+        case MallocFallbackState::Undecided:
+            determineMallocFallbackState();
+            continue;
+        case MallocFallbackState::FallBackToMalloc:
+            return api::free(p);
+        case MallocFallbackState::DoNotFallBack:
+            break;
+        }
+        break;
+    }
+    
+    // If debug heap is enabled, s_mallocFallbackState becomes MallocFallbackState::FallBackToMalloc.
+    BASSERT(!Environment::get()->isDebugHeapEnabled());
+    
+    RELEASE_BASSERT(handle.isInitialized());
+    
+    IsoTLS* tls = ensureEntries(std::max(handle.allocatorOffset(), handle.deallocatorOffset()));
+    
+    tls->deallocateFast<Config>(handle, handle.deallocatorOffset(), p);
 }
 
 inline IsoTLS* IsoTLS::get()
@@ -133,7 +172,7 @@ template<typename Type>
 void IsoTLS::ensureHeap(api::IsoHeap<Type>& handle)
 {
     if (!handle.isInitialized()) {
-        std::lock_guard<StaticMutex> locker(handle.m_initializationLock);
+        std::lock_guard<Mutex> locker(handle.m_initializationLock);
         if (!handle.isInitialized()) {
             auto* heap = new IsoHeapImpl<typename api::IsoHeap<Type>::Config>();
             std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -151,16 +190,8 @@ BNO_INLINE IsoTLS* IsoTLS::ensureHeapAndEntries(api::IsoHeap<Type>& handle)
         !get()
         || handle.allocatorOffset() >= get()->m_extent
         || handle.deallocatorOffset() >= get()->m_extent);
-    unsigned offset;
-    if (isUsingDebugHeap()) {
-        if (IsoTLS* result = get())
-            return result;
-        offset = 0;
-    } else {
-        ensureHeap(handle);
-        offset = std::max(handle.allocatorOffset(), handle.deallocatorOffset());
-    }
-    return ensureEntries(offset);
+    ensureHeap(handle);
+    return ensureEntries(std::max(handle.allocatorOffset(), handle.deallocatorOffset()));
 }
 
 } // namespace bmalloc