mirror of
https://github.com/darlinghq/darling-bmalloc.git
synced 2024-11-26 22:00:22 +00:00
bmalloc-7603.1.30.0.34
This commit is contained in:
parent
f1047d896b
commit
b2e63a5448
35
CMakeLists.txt
Normal file
35
CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
set_property(DIRECTORY . PROPERTY FOLDER "bmalloc")
|
||||
|
||||
set(bmalloc_INCLUDE_DIRECTORIES
|
||||
"${BMALLOC_DIR}"
|
||||
)
|
||||
|
||||
set(bmalloc_SOURCES
|
||||
bmalloc/Allocator.cpp
|
||||
bmalloc/Cache.cpp
|
||||
bmalloc/Deallocator.cpp
|
||||
bmalloc/Environment.cpp
|
||||
bmalloc/Heap.cpp
|
||||
bmalloc/LargeMap.cpp
|
||||
bmalloc/Logging.cpp
|
||||
bmalloc/ObjectType.cpp
|
||||
bmalloc/StaticMutex.cpp
|
||||
bmalloc/VMHeap.cpp
|
||||
bmalloc/mbmalloc.cpp
|
||||
)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
list(APPEND bmalloc_SOURCES
|
||||
bmalloc/Zone.cpp
|
||||
)
|
||||
endif ()
|
||||
|
||||
set(bmalloc_LIBRARIES
|
||||
${CMAKE_DL_LIBS}
|
||||
)
|
||||
|
||||
WEBKIT_WRAP_SOURCELIST(${bmalloc_SOURCES})
|
||||
include_directories(${bmalloc_INCLUDE_DIRECTORIES})
|
||||
add_library(bmalloc STATIC ${bmalloc_SOURCES})
|
||||
target_link_libraries(bmalloc ${bmalloc_LIBRARIES})
|
||||
set_target_properties(bmalloc PROPERTIES COMPILE_DEFINITIONS "BUILDING_bmalloc")
|
115
Configurations/Base.xcconfig
Normal file
115
Configurations/Base.xcconfig
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../../../../Internal/Configurations/HaveInternalSDK.xcconfig"
|
||||
|
||||
USE_INTERNAL_SDK = $(USE_INTERNAL_SDK_$(CONFIGURATION));
|
||||
USE_INTERNAL_SDK_Production = YES;
|
||||
USE_INTERNAL_SDK_Debug = $(HAVE_INTERNAL_SDK);
|
||||
USE_INTERNAL_SDK_Release = $(HAVE_INTERNAL_SDK);
|
||||
|
||||
CLANG_CXX_LANGUAGE_STANDARD = gnu++14;
|
||||
CLANG_CXX_LIBRARY = libc++;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_CXX0X_EXTENSIONS = NO;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DEBUGGING_SYMBOLS = default;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||
GCC_ENABLE_CPP_RTTI = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_ENABLE_SYMBOL_SEPARATION = NO;
|
||||
GCC_FAST_OBJC_DISPATCH = YES;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OBJC_CALL_CXX_CDTORS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(DEBUG_DEFINES) $(inherited);
|
||||
GCC_STRICT_ALIASING = YES;
|
||||
GCC_THREADSAFE_STATICS = NO;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
// FIXME: <http://webkit.org/b/107093> WTF should build with -Wshorten-64-to-32
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = $(GCC_WARN_64_TO_32_BIT_CONVERSION_$(CURRENT_ARCH));
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_ = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_armv7 = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_armv7k = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_armv7s = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_arm64 = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_i386 = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION_x86_64 = NO;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
WARNING_CFLAGS = -Wall -Wextra -Wcast-qual -Wchar-subscripts -Wextra-tokens -Wformat=2 -Winit-self -Wmissing-format-attribute -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wundef -Wwrite-strings -Wexit-time-destructors -Wglobal-constructors -Wtautological-compare -Wimplicit-fallthrough;
|
||||
|
||||
TARGET_MAC_OS_X_VERSION_MAJOR = $(TARGET_MAC_OS_X_VERSION_MAJOR$(MACOSX_DEPLOYMENT_TARGET:suffix:identifier));
|
||||
TARGET_MAC_OS_X_VERSION_MAJOR_10 = 101000;
|
||||
TARGET_MAC_OS_X_VERSION_MAJOR_11 = 101100;
|
||||
TARGET_MAC_OS_X_VERSION_MAJOR_12 = 101200;
|
||||
TARGET_MAC_OS_X_VERSION_MAJOR_13 = 101300;
|
||||
|
||||
SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx appletvos appletvsimulator watchos watchsimulator;
|
||||
|
||||
// DEBUG_DEFINES, GCC_OPTIMIZATION_LEVEL, STRIP_INSTALLED_PRODUCT and DEAD_CODE_STRIPPING vary between the debug and normal variants.
|
||||
// We set up the values for each variant here, and have the Debug configuration in the Xcode project use the _debug variant.
|
||||
DEBUG_DEFINES_debug = ;
|
||||
DEBUG_DEFINES_normal = NDEBUG;
|
||||
DEBUG_DEFINES = $(DEBUG_DEFINES_$(CURRENT_VARIANT));
|
||||
|
||||
GCC_OPTIMIZATION_LEVEL = $(GCC_OPTIMIZATION_LEVEL_$(CURRENT_VARIANT));
|
||||
GCC_OPTIMIZATION_LEVEL_normal = 3;
|
||||
GCC_OPTIMIZATION_LEVEL_debug = 0;
|
||||
|
||||
STRIP_INSTALLED_PRODUCT = $(STRIP_INSTALLED_PRODUCT_$(CURRENT_VARIANT));
|
||||
STRIP_INSTALLED_PRODUCT_normal = YES;
|
||||
STRIP_INSTALLED_PRODUCT_debug = NO;
|
||||
|
||||
DEAD_CODE_STRIPPING_debug = NO;
|
||||
DEAD_CODE_STRIPPING_normal = YES;
|
||||
DEAD_CODE_STRIPPING = $(DEAD_CODE_STRIPPING_$(CURRENT_VARIANT));
|
||||
|
||||
SDKROOT = macosx.internal;
|
||||
|
||||
OTHER_CFLAGS = $(ASAN_OTHER_CFLAGS);
|
||||
OTHER_CPLUSPLUSFLAGS = $(ASAN_OTHER_CPLUSPLUSFLAGS);
|
||||
OTHER_LDFLAGS = $(ASAN_OTHER_LDFLAGS);
|
42
Configurations/DebugRelease.xcconfig
Normal file
42
Configurations/DebugRelease.xcconfig
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "Base.xcconfig"
|
||||
|
||||
ARCHS = $(ARCHS_STANDARD_32_64_BIT);
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
|
||||
TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR);
|
||||
|
||||
MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(PLATFORM_NAME)_$(TARGET_MAC_OS_X_VERSION_MAJOR));
|
||||
MACOSX_DEPLOYMENT_TARGET_macosx_101000 = 10.10;
|
||||
MACOSX_DEPLOYMENT_TARGET_macosx_101100 = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET_macosx_101200 = 10.12;
|
||||
MACOSX_DEPLOYMENT_TARGET_macosx_101300 = 10.13;
|
||||
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
|
||||
SDKROOT = $(SDKROOT_$(USE_INTERNAL_SDK));
|
||||
SDKROOT_ = macosx;
|
||||
SDKROOT_YES = macosx.internal;
|
30
Configurations/bmalloc.xcconfig
Normal file
30
Configurations/bmalloc.xcconfig
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
INSTALL_PATH = /usr/local/lib;
|
||||
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/bmalloc;
|
||||
PRODUCT_NAME = bmalloc;
|
||||
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
28
Configurations/mbmalloc.xcconfig
Normal file
28
Configurations/mbmalloc.xcconfig
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
INSTALL_PATH = /usr/local/lib;
|
||||
PRODUCT_NAME = mbmalloc;
|
||||
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
546
bmalloc.xcodeproj/project.pbxproj
Normal file
546
bmalloc.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,546 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1400274918F89C1300115C97 /* Heap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14DA320C18875B09007269E0 /* Heap.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
1400274A18F89C2300115C97 /* VMHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = 144F7BFC18BFC517003537F3 /* VMHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
140FA00319CE429C00FFD3C8 /* BumpRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 140FA00219CE429C00FFD3C8 /* BumpRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
140FA00519CE4B6800FFD3C8 /* LineMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 140FA00419CE4B6800FFD3C8 /* LineMetadata.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
141D9B001C8E51C0000ABBA0 /* List.h in Headers */ = {isa = PBXBuildFile; fileRef = 141D9AFF1C8E51C0000ABBA0 /* List.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
143CB81C19022BC900B16A45 /* StaticMutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143CB81A19022BC900B16A45 /* StaticMutex.cpp */; };
|
||||
143CB81D19022BC900B16A45 /* StaticMutex.h in Headers */ = {isa = PBXBuildFile; fileRef = 143CB81B19022BC900B16A45 /* StaticMutex.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
1440AFCB1A95261100837FAA /* Zone.h in Headers */ = {isa = PBXBuildFile; fileRef = 1440AFCA1A95261100837FAA /* Zone.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
1440AFCD1A9527AF00837FAA /* Zone.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440AFCC1A9527AF00837FAA /* Zone.cpp */; };
|
||||
1448C30018F3754600502839 /* mbmalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1448C2FF18F3754300502839 /* mbmalloc.cpp */; };
|
||||
1448C30118F3754C00502839 /* bmalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 1448C2FE18F3754300502839 /* bmalloc.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
144BE11F1CA346520099C8C0 /* Object.h in Headers */ = {isa = PBXBuildFile; fileRef = 144BE11E1CA346520099C8C0 /* Object.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
144C07F41C7B70260051BB6A /* LargeMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 144C07F21C7B70260051BB6A /* LargeMap.cpp */; };
|
||||
144C07F51C7B70260051BB6A /* LargeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 144C07F31C7B70260051BB6A /* LargeMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
147DC6E31CA5B70B00724E8D /* Chunk.h in Headers */ = {isa = PBXBuildFile; fileRef = 147DC6E21CA5B70B00724E8D /* Chunk.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14895D911A3A319C0006235D /* Environment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14895D8F1A3A319C0006235D /* Environment.cpp */; };
|
||||
14895D921A3A319C0006235D /* Environment.h in Headers */ = {isa = PBXBuildFile; fileRef = 14895D901A3A319C0006235D /* Environment.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
148EFAE81D6B953B008E721E /* ScopeExit.h in Headers */ = {isa = PBXBuildFile; fileRef = 148EFAE61D6B953B008E721E /* ScopeExit.h */; };
|
||||
14C8992B1CC485E70027A057 /* Map.h in Headers */ = {isa = PBXBuildFile; fileRef = 14C8992A1CC485E70027A057 /* Map.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14C8992D1CC578330027A057 /* LargeRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 14C8992C1CC578330027A057 /* LargeRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14C919C918FCC59F0028DB43 /* BPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 14C919C818FCC59F0028DB43 /* BPlatform.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14CC394C18EA8858004AFE34 /* libbmalloc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14F271BE18EA3963008C152F /* libbmalloc.a */; };
|
||||
14DD789018F48CEB00950702 /* Sizes.h in Headers */ = {isa = PBXBuildFile; fileRef = 145F6874179DF84100D65598 /* Sizes.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD789318F48D0F00950702 /* ObjectType.h in Headers */ = {isa = PBXBuildFile; fileRef = 1485656018A43DBA00ED6942 /* ObjectType.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD789818F48D4A00950702 /* Allocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 145F6856179DC8CA00D65598 /* Allocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD789918F48D4A00950702 /* Cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 144469E517A46BFE00F9EA1D /* Cache.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD789A18F48D4A00950702 /* Deallocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 145F685A179DC90200D65598 /* Deallocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD789C18F48D4A00950702 /* BumpAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1413E462189DE1CD00546D68 /* BumpAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78BC18F48D6B00950702 /* SmallLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 1452478618BC757C00F80098 /* SmallLine.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78BD18F48D6B00950702 /* SmallPage.h in Headers */ = {isa = PBXBuildFile; fileRef = 143E29ED18CAE90500FE8A0F /* SmallPage.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78C518F48D7500950702 /* Algorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 1421A87718EE462A00B4DD68 /* Algorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78C618F48D7500950702 /* AsyncTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 1417F65218BA88A00076FA3F /* AsyncTask.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78C718F48D7500950702 /* BAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 1413E468189EEDE400546D68 /* BAssert.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78C818F48D7500950702 /* FixedVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D9DB4517F2447100EAAB79 /* FixedVector.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78C918F48D7500950702 /* Inline.h in Headers */ = {isa = PBXBuildFile; fileRef = 1413E460189DCE1E00546D68 /* Inline.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78CA18F48D7500950702 /* Mutex.h in Headers */ = {isa = PBXBuildFile; fileRef = 144DCED617A649D90093B2F2 /* Mutex.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78CB18F48D7500950702 /* PerProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 14446A0717A61FA400F9EA1D /* PerProcess.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78CC18F48D7500950702 /* PerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 144469FD17A61F1F00F9EA1D /* PerThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78CD18F48D7500950702 /* Range.h in Headers */ = {isa = PBXBuildFile; fileRef = 145F6878179E3A4400D65598 /* Range.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78CE18F48D7500950702 /* Syscall.h in Headers */ = {isa = PBXBuildFile; fileRef = 1417F64F18B7280C0076FA3F /* Syscall.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78CF18F48D7500950702 /* Vector.h in Headers */ = {isa = PBXBuildFile; fileRef = 1479E21217A1A255006D4E9D /* Vector.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14DD78D018F48D7500950702 /* VMAllocate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1479E21417A1A63E006D4E9D /* VMAllocate.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
14F271C318EA3978008C152F /* Allocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 145F6855179DC8CA00D65598 /* Allocator.cpp */; };
|
||||
14F271C418EA397B008C152F /* Cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 144469E417A46BFE00F9EA1D /* Cache.cpp */; };
|
||||
14F271C518EA397E008C152F /* Deallocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 145F6859179DC90200D65598 /* Deallocator.cpp */; };
|
||||
14F271C718EA3990008C152F /* Heap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14DA320E18875D9F007269E0 /* Heap.cpp */; };
|
||||
14F271C818EA3990008C152F /* ObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14105E8318E14374003A106E /* ObjectType.cpp */; };
|
||||
14F271C918EA3990008C152F /* VMHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 144F7BFB18BFC517003537F3 /* VMHeap.cpp */; };
|
||||
4426E2801C838EE0008EB042 /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4426E27E1C838EE0008EB042 /* Logging.cpp */; };
|
||||
4426E2811C838EE0008EB042 /* Logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 4426E27F1C838EE0008EB042 /* Logging.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
4426E2831C839547008EB042 /* BSoftLinking.h in Headers */ = {isa = PBXBuildFile; fileRef = 4426E2821C839547008EB042 /* BSoftLinking.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
14CC394D18EA8861004AFE34 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 145F6837179DC45F00D65598 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 14F271BD18EA3963008C152F;
|
||||
remoteInfo = bmalloc;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
140FA00219CE429C00FFD3C8 /* BumpRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BumpRange.h; path = bmalloc/BumpRange.h; sourceTree = "<group>"; };
|
||||
140FA00419CE4B6800FFD3C8 /* LineMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineMetadata.h; path = bmalloc/LineMetadata.h; sourceTree = "<group>"; };
|
||||
14105E8318E14374003A106E /* ObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectType.cpp; path = bmalloc/ObjectType.cpp; sourceTree = "<group>"; };
|
||||
1413E460189DCE1E00546D68 /* Inline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Inline.h; path = bmalloc/Inline.h; sourceTree = "<group>"; };
|
||||
1413E462189DE1CD00546D68 /* BumpAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BumpAllocator.h; path = bmalloc/BumpAllocator.h; sourceTree = "<group>"; };
|
||||
1413E468189EEDE400546D68 /* BAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BAssert.h; path = bmalloc/BAssert.h; sourceTree = "<group>"; };
|
||||
1417F64F18B7280C0076FA3F /* Syscall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Syscall.h; path = bmalloc/Syscall.h; sourceTree = "<group>"; };
|
||||
1417F65218BA88A00076FA3F /* AsyncTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AsyncTask.h; path = bmalloc/AsyncTask.h; sourceTree = "<group>"; };
|
||||
141D9AFF1C8E51C0000ABBA0 /* List.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = List.h; path = bmalloc/List.h; sourceTree = "<group>"; };
|
||||
1421A87718EE462A00B4DD68 /* Algorithm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Algorithm.h; path = bmalloc/Algorithm.h; sourceTree = "<group>"; };
|
||||
143CB81A19022BC900B16A45 /* StaticMutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StaticMutex.cpp; path = bmalloc/StaticMutex.cpp; sourceTree = "<group>"; };
|
||||
143CB81B19022BC900B16A45 /* StaticMutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StaticMutex.h; path = bmalloc/StaticMutex.h; sourceTree = "<group>"; };
|
||||
143E29ED18CAE90500FE8A0F /* SmallPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SmallPage.h; path = bmalloc/SmallPage.h; sourceTree = "<group>"; };
|
||||
1440AFCA1A95261100837FAA /* Zone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Zone.h; path = bmalloc/Zone.h; sourceTree = "<group>"; };
|
||||
1440AFCC1A9527AF00837FAA /* Zone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Zone.cpp; path = bmalloc/Zone.cpp; sourceTree = "<group>"; };
|
||||
144469E417A46BFE00F9EA1D /* Cache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Cache.cpp; path = bmalloc/Cache.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
144469E517A46BFE00F9EA1D /* Cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Cache.h; path = bmalloc/Cache.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
144469FD17A61F1F00F9EA1D /* PerThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = PerThread.h; path = bmalloc/PerThread.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
14446A0717A61FA400F9EA1D /* PerProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PerProcess.h; path = bmalloc/PerProcess.h; sourceTree = "<group>"; };
|
||||
1448C2FE18F3754300502839 /* bmalloc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = bmalloc.h; path = bmalloc/bmalloc.h; sourceTree = "<group>"; };
|
||||
1448C2FF18F3754300502839 /* mbmalloc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mbmalloc.cpp; path = bmalloc/mbmalloc.cpp; sourceTree = "<group>"; };
|
||||
144BE11E1CA346520099C8C0 /* Object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Object.h; path = bmalloc/Object.h; sourceTree = "<group>"; };
|
||||
144C07F21C7B70260051BB6A /* LargeMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LargeMap.cpp; path = bmalloc/LargeMap.cpp; sourceTree = "<group>"; };
|
||||
144C07F31C7B70260051BB6A /* LargeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LargeMap.h; path = bmalloc/LargeMap.h; sourceTree = "<group>"; };
|
||||
144DCED617A649D90093B2F2 /* Mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mutex.h; path = bmalloc/Mutex.h; sourceTree = "<group>"; };
|
||||
144F7BFB18BFC517003537F3 /* VMHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VMHeap.cpp; path = bmalloc/VMHeap.cpp; sourceTree = "<group>"; };
|
||||
144F7BFC18BFC517003537F3 /* VMHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VMHeap.h; path = bmalloc/VMHeap.h; sourceTree = "<group>"; };
|
||||
1452478618BC757C00F80098 /* SmallLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SmallLine.h; path = bmalloc/SmallLine.h; sourceTree = "<group>"; };
|
||||
145F6855179DC8CA00D65598 /* Allocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Allocator.cpp; path = bmalloc/Allocator.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
145F6856179DC8CA00D65598 /* Allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Allocator.h; path = bmalloc/Allocator.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
145F6859179DC90200D65598 /* Deallocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Deallocator.cpp; path = bmalloc/Deallocator.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
145F685A179DC90200D65598 /* Deallocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Deallocator.h; path = bmalloc/Deallocator.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
145F6874179DF84100D65598 /* Sizes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sizes.h; path = bmalloc/Sizes.h; sourceTree = "<group>"; };
|
||||
145F6878179E3A4400D65598 /* Range.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Range.h; path = bmalloc/Range.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
1479E21217A1A255006D4E9D /* Vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Vector.h; path = bmalloc/Vector.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
1479E21417A1A63E006D4E9D /* VMAllocate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = VMAllocate.h; path = bmalloc/VMAllocate.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
147DC6E21CA5B70B00724E8D /* Chunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Chunk.h; path = bmalloc/Chunk.h; sourceTree = "<group>"; };
|
||||
1485656018A43DBA00ED6942 /* ObjectType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjectType.h; path = bmalloc/ObjectType.h; sourceTree = "<group>"; };
|
||||
14895D8F1A3A319C0006235D /* Environment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Environment.cpp; path = bmalloc/Environment.cpp; sourceTree = "<group>"; };
|
||||
14895D901A3A319C0006235D /* Environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Environment.h; path = bmalloc/Environment.h; sourceTree = "<group>"; };
|
||||
148EFAE61D6B953B008E721E /* ScopeExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScopeExit.h; path = bmalloc/ScopeExit.h; sourceTree = "<group>"; };
|
||||
14B650C518F39F4800751968 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
|
||||
14B650C618F39F4800751968 /* bmalloc.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = bmalloc.xcconfig; sourceTree = "<group>"; };
|
||||
14B650C718F39F4800751968 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
|
||||
14B650C918F3A04200751968 /* mbmalloc.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mbmalloc.xcconfig; sourceTree = "<group>"; };
|
||||
14C8992A1CC485E70027A057 /* Map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Map.h; path = bmalloc/Map.h; sourceTree = "<group>"; };
|
||||
14C8992C1CC578330027A057 /* LargeRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LargeRange.h; path = bmalloc/LargeRange.h; sourceTree = "<group>"; };
|
||||
14C919C818FCC59F0028DB43 /* BPlatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BPlatform.h; path = bmalloc/BPlatform.h; sourceTree = "<group>"; };
|
||||
14CC394418EA8743004AFE34 /* libmbmalloc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libmbmalloc.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
14D9DB4517F2447100EAAB79 /* FixedVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = FixedVector.h; path = bmalloc/FixedVector.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
14DA320C18875B09007269E0 /* Heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Heap.h; path = bmalloc/Heap.h; sourceTree = "<group>"; };
|
||||
14DA320E18875D9F007269E0 /* Heap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Heap.cpp; path = bmalloc/Heap.cpp; sourceTree = "<group>"; };
|
||||
14F271BE18EA3963008C152F /* libbmalloc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libbmalloc.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4426E27E1C838EE0008EB042 /* Logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Logging.cpp; path = bmalloc/Logging.cpp; sourceTree = "<group>"; };
|
||||
4426E27F1C838EE0008EB042 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = bmalloc/Logging.h; sourceTree = "<group>"; };
|
||||
4426E2821C839547008EB042 /* BSoftLinking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSoftLinking.h; path = bmalloc/darwin/BSoftLinking.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
14CC394118EA8743004AFE34 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14CC394C18EA8858004AFE34 /* libbmalloc.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14F271BB18EA3963008C152F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1448C2FD18F3752B00502839 /* api */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1448C2FE18F3754300502839 /* bmalloc.h */,
|
||||
1448C2FF18F3754300502839 /* mbmalloc.cpp */,
|
||||
);
|
||||
name = api;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
145F6836179DC45F00D65598 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1448C2FD18F3752B00502839 /* api */,
|
||||
14D9DB4D17F2865C00EAAB79 /* cache */,
|
||||
14B650C418F39F4800751968 /* Configurations */,
|
||||
14D9DB4E17F2866E00EAAB79 /* heap */,
|
||||
147AAA9C18CE6010002201E4 /* heap: large */,
|
||||
147AAA9A18CE5FD3002201E4 /* heap: small */,
|
||||
145F6840179DC45F00D65598 /* Products */,
|
||||
14D9DB4F17F2868900EAAB79 /* stdlib */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
145F6840179DC45F00D65598 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14F271BE18EA3963008C152F /* libbmalloc.a */,
|
||||
14CC394418EA8743004AFE34 /* libmbmalloc.dylib */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
147AAA9A18CE5FD3002201E4 /* heap: small */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1452478618BC757C00F80098 /* SmallLine.h */,
|
||||
143E29ED18CAE90500FE8A0F /* SmallPage.h */,
|
||||
);
|
||||
name = "heap: small";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
147AAA9C18CE6010002201E4 /* heap: large */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
144C07F21C7B70260051BB6A /* LargeMap.cpp */,
|
||||
144C07F31C7B70260051BB6A /* LargeMap.h */,
|
||||
14C8992C1CC578330027A057 /* LargeRange.h */,
|
||||
);
|
||||
name = "heap: large";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14B650C418F39F4800751968 /* Configurations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14B650C518F39F4800751968 /* Base.xcconfig */,
|
||||
14B650C618F39F4800751968 /* bmalloc.xcconfig */,
|
||||
14B650C718F39F4800751968 /* DebugRelease.xcconfig */,
|
||||
14B650C918F3A04200751968 /* mbmalloc.xcconfig */,
|
||||
);
|
||||
path = Configurations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D9DB4D17F2865C00EAAB79 /* cache */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
145F6855179DC8CA00D65598 /* Allocator.cpp */,
|
||||
145F6856179DC8CA00D65598 /* Allocator.h */,
|
||||
1413E462189DE1CD00546D68 /* BumpAllocator.h */,
|
||||
144469E417A46BFE00F9EA1D /* Cache.cpp */,
|
||||
144469E517A46BFE00F9EA1D /* Cache.h */,
|
||||
145F6859179DC90200D65598 /* Deallocator.cpp */,
|
||||
145F685A179DC90200D65598 /* Deallocator.h */,
|
||||
);
|
||||
name = cache;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D9DB4E17F2866E00EAAB79 /* heap */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
140FA00219CE429C00FFD3C8 /* BumpRange.h */,
|
||||
147DC6E21CA5B70B00724E8D /* Chunk.h */,
|
||||
14895D8F1A3A319C0006235D /* Environment.cpp */,
|
||||
14895D901A3A319C0006235D /* Environment.h */,
|
||||
14DA320E18875D9F007269E0 /* Heap.cpp */,
|
||||
14DA320C18875B09007269E0 /* Heap.h */,
|
||||
140FA00419CE4B6800FFD3C8 /* LineMetadata.h */,
|
||||
144BE11E1CA346520099C8C0 /* Object.h */,
|
||||
14105E8318E14374003A106E /* ObjectType.cpp */,
|
||||
1485656018A43DBA00ED6942 /* ObjectType.h */,
|
||||
145F6874179DF84100D65598 /* Sizes.h */,
|
||||
144F7BFB18BFC517003537F3 /* VMHeap.cpp */,
|
||||
144F7BFC18BFC517003537F3 /* VMHeap.h */,
|
||||
1440AFCC1A9527AF00837FAA /* Zone.cpp */,
|
||||
1440AFCA1A95261100837FAA /* Zone.h */,
|
||||
);
|
||||
name = heap;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
14D9DB4F17F2868900EAAB79 /* stdlib */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4408F2961C9896C40012EC64 /* darwin */,
|
||||
1421A87718EE462A00B4DD68 /* Algorithm.h */,
|
||||
1417F65218BA88A00076FA3F /* AsyncTask.h */,
|
||||
1413E468189EEDE400546D68 /* BAssert.h */,
|
||||
14C919C818FCC59F0028DB43 /* BPlatform.h */,
|
||||
14D9DB4517F2447100EAAB79 /* FixedVector.h */,
|
||||
1413E460189DCE1E00546D68 /* Inline.h */,
|
||||
141D9AFF1C8E51C0000ABBA0 /* List.h */,
|
||||
4426E27E1C838EE0008EB042 /* Logging.cpp */,
|
||||
4426E27F1C838EE0008EB042 /* Logging.h */,
|
||||
14C8992A1CC485E70027A057 /* Map.h */,
|
||||
144DCED617A649D90093B2F2 /* Mutex.h */,
|
||||
14446A0717A61FA400F9EA1D /* PerProcess.h */,
|
||||
144469FD17A61F1F00F9EA1D /* PerThread.h */,
|
||||
145F6878179E3A4400D65598 /* Range.h */,
|
||||
148EFAE61D6B953B008E721E /* ScopeExit.h */,
|
||||
143CB81A19022BC900B16A45 /* StaticMutex.cpp */,
|
||||
143CB81B19022BC900B16A45 /* StaticMutex.h */,
|
||||
1417F64F18B7280C0076FA3F /* Syscall.h */,
|
||||
1479E21217A1A255006D4E9D /* Vector.h */,
|
||||
1479E21417A1A63E006D4E9D /* VMAllocate.h */,
|
||||
);
|
||||
name = stdlib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4408F2961C9896C40012EC64 /* darwin */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4426E2821C839547008EB042 /* BSoftLinking.h */,
|
||||
);
|
||||
name = darwin;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
14CC394218EA8743004AFE34 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14F271BC18EA3963008C152F /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14DD78C518F48D7500950702 /* Algorithm.h in Headers */,
|
||||
14DD789818F48D4A00950702 /* Allocator.h in Headers */,
|
||||
14DD78C618F48D7500950702 /* AsyncTask.h in Headers */,
|
||||
14DD78C718F48D7500950702 /* BAssert.h in Headers */,
|
||||
1448C30118F3754C00502839 /* bmalloc.h in Headers */,
|
||||
14C919C918FCC59F0028DB43 /* BPlatform.h in Headers */,
|
||||
4426E2831C839547008EB042 /* BSoftLinking.h in Headers */,
|
||||
14DD789C18F48D4A00950702 /* BumpAllocator.h in Headers */,
|
||||
140FA00319CE429C00FFD3C8 /* BumpRange.h in Headers */,
|
||||
14DD789918F48D4A00950702 /* Cache.h in Headers */,
|
||||
147DC6E31CA5B70B00724E8D /* Chunk.h in Headers */,
|
||||
14DD789A18F48D4A00950702 /* Deallocator.h in Headers */,
|
||||
14895D921A3A319C0006235D /* Environment.h in Headers */,
|
||||
14DD78C818F48D7500950702 /* FixedVector.h in Headers */,
|
||||
1400274918F89C1300115C97 /* Heap.h in Headers */,
|
||||
14DD78C918F48D7500950702 /* Inline.h in Headers */,
|
||||
144C07F51C7B70260051BB6A /* LargeMap.h in Headers */,
|
||||
14C8992D1CC578330027A057 /* LargeRange.h in Headers */,
|
||||
140FA00519CE4B6800FFD3C8 /* LineMetadata.h in Headers */,
|
||||
141D9B001C8E51C0000ABBA0 /* List.h in Headers */,
|
||||
4426E2811C838EE0008EB042 /* Logging.h in Headers */,
|
||||
14C8992B1CC485E70027A057 /* Map.h in Headers */,
|
||||
14DD78CA18F48D7500950702 /* Mutex.h in Headers */,
|
||||
144BE11F1CA346520099C8C0 /* Object.h in Headers */,
|
||||
14DD789318F48D0F00950702 /* ObjectType.h in Headers */,
|
||||
14DD78CB18F48D7500950702 /* PerProcess.h in Headers */,
|
||||
14DD78CC18F48D7500950702 /* PerThread.h in Headers */,
|
||||
14DD78CD18F48D7500950702 /* Range.h in Headers */,
|
||||
148EFAE81D6B953B008E721E /* ScopeExit.h in Headers */,
|
||||
14DD789018F48CEB00950702 /* Sizes.h in Headers */,
|
||||
14DD78BC18F48D6B00950702 /* SmallLine.h in Headers */,
|
||||
14DD78BD18F48D6B00950702 /* SmallPage.h in Headers */,
|
||||
143CB81D19022BC900B16A45 /* StaticMutex.h in Headers */,
|
||||
14DD78CE18F48D7500950702 /* Syscall.h in Headers */,
|
||||
14DD78CF18F48D7500950702 /* Vector.h in Headers */,
|
||||
14DD78D018F48D7500950702 /* VMAllocate.h in Headers */,
|
||||
1400274A18F89C2300115C97 /* VMHeap.h in Headers */,
|
||||
1440AFCB1A95261100837FAA /* Zone.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
14CC394318EA8743004AFE34 /* mbmalloc */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 14CC394518EA8743004AFE34 /* Build configuration list for PBXNativeTarget "mbmalloc" */;
|
||||
buildPhases = (
|
||||
14CC394018EA8743004AFE34 /* Sources */,
|
||||
14CC394118EA8743004AFE34 /* Frameworks */,
|
||||
14CC394218EA8743004AFE34 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
14CC394E18EA8861004AFE34 /* PBXTargetDependency */,
|
||||
);
|
||||
name = mbmalloc;
|
||||
productName = mbmalloc;
|
||||
productReference = 14CC394418EA8743004AFE34 /* libmbmalloc.dylib */;
|
||||
productType = "com.apple.product-type.library.dynamic";
|
||||
};
|
||||
14F271BD18EA3963008C152F /* bmalloc */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 14F271BF18EA3963008C152F /* Build configuration list for PBXNativeTarget "bmalloc" */;
|
||||
buildPhases = (
|
||||
14F271BA18EA3963008C152F /* Sources */,
|
||||
14F271BB18EA3963008C152F /* Frameworks */,
|
||||
14F271BC18EA3963008C152F /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = bmalloc;
|
||||
productName = bmalloc;
|
||||
productReference = 14F271BE18EA3963008C152F /* libbmalloc.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
145F6837179DC45F00D65598 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0700;
|
||||
LastUpgradeCheck = 0700;
|
||||
};
|
||||
buildConfigurationList = 145F683A179DC45F00D65598 /* Build configuration list for PBXProject "bmalloc" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 145F6836179DC45F00D65598;
|
||||
productRefGroup = 145F6840179DC45F00D65598 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
14F271BD18EA3963008C152F /* bmalloc */,
|
||||
14CC394318EA8743004AFE34 /* mbmalloc */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
14CC394018EA8743004AFE34 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1448C30018F3754600502839 /* mbmalloc.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
14F271BA18EA3963008C152F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
14F271C318EA3978008C152F /* Allocator.cpp in Sources */,
|
||||
14F271C418EA397B008C152F /* Cache.cpp in Sources */,
|
||||
14F271C518EA397E008C152F /* Deallocator.cpp in Sources */,
|
||||
14895D911A3A319C0006235D /* Environment.cpp in Sources */,
|
||||
14F271C718EA3990008C152F /* Heap.cpp in Sources */,
|
||||
144C07F41C7B70260051BB6A /* LargeMap.cpp in Sources */,
|
||||
4426E2801C838EE0008EB042 /* Logging.cpp in Sources */,
|
||||
14F271C818EA3990008C152F /* ObjectType.cpp in Sources */,
|
||||
143CB81C19022BC900B16A45 /* StaticMutex.cpp in Sources */,
|
||||
14F271C918EA3990008C152F /* VMHeap.cpp in Sources */,
|
||||
1440AFCD1A9527AF00837FAA /* Zone.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
14CC394E18EA8861004AFE34 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 14F271BD18EA3963008C152F /* bmalloc */;
|
||||
targetProxy = 14CC394D18EA8861004AFE34 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
14202F0F18F37C15006C37DB /* Production */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C518F39F4800751968 /* Base.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Production;
|
||||
};
|
||||
14202F1018F37C15006C37DB /* Production */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C618F39F4800751968 /* bmalloc.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Production;
|
||||
};
|
||||
14202F1118F37C15006C37DB /* Production */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C918F3A04200751968 /* mbmalloc.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Production;
|
||||
};
|
||||
145F684A179DC45F00D65598 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C718F39F4800751968 /* DebugRelease.xcconfig */;
|
||||
buildSettings = {
|
||||
DEAD_CODE_STRIPPING = "$(DEAD_CODE_STRIPPING_debug)";
|
||||
DEBUG_DEFINES = "$(DEBUG_DEFINES_debug)";
|
||||
GCC_OPTIMIZATION_LEVEL = "$(GCC_OPTIMIZATION_LEVEL_debug)";
|
||||
STRIP_INSTALLED_PRODUCT = "$(STRIP_INSTALLED_PRODUCT_debug)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
145F684B179DC45F00D65598 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C718F39F4800751968 /* DebugRelease.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
14CC394618EA8743004AFE34 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C918F3A04200751968 /* mbmalloc.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
14CC394718EA8743004AFE34 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C918F3A04200751968 /* mbmalloc.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
14F271C018EA3963008C152F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C618F39F4800751968 /* bmalloc.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
14F271C118EA3963008C152F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14B650C618F39F4800751968 /* bmalloc.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
145F683A179DC45F00D65598 /* Build configuration list for PBXProject "bmalloc" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
145F684A179DC45F00D65598 /* Debug */,
|
||||
145F684B179DC45F00D65598 /* Release */,
|
||||
14202F0F18F37C15006C37DB /* Production */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Production;
|
||||
};
|
||||
14CC394518EA8743004AFE34 /* Build configuration list for PBXNativeTarget "mbmalloc" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
14CC394618EA8743004AFE34 /* Debug */,
|
||||
14CC394718EA8743004AFE34 /* Release */,
|
||||
14202F1118F37C15006C37DB /* Production */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Production;
|
||||
};
|
||||
14F271BF18EA3963008C152F /* Build configuration list for PBXNativeTarget "bmalloc" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
14F271C018EA3963008C152F /* Debug */,
|
||||
14F271C118EA3963008C152F /* Release */,
|
||||
14202F1018F37C15006C37DB /* Production */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Production;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 145F6837179DC45F00D65598 /* Project object */;
|
||||
}
|
128
bmalloc/Algorithm.h
Normal file
128
bmalloc/Algorithm.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Algorithm_h
|
||||
#define Algorithm_h
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "BAssert.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <chrono>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// Versions of min and max that are compatible with compile-time constants.
|
||||
template<typename T> inline constexpr T max(T a, T b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T> inline constexpr T min(T a, T b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template<typename T> inline constexpr T mask(T value, uintptr_t mask)
|
||||
{
|
||||
return reinterpret_cast<T>(reinterpret_cast<uintptr_t>(value) & mask);
|
||||
}
|
||||
|
||||
template<typename T> inline constexpr bool test(T value, uintptr_t mask)
|
||||
{
|
||||
return !!(reinterpret_cast<uintptr_t>(value) & mask);
|
||||
}
|
||||
|
||||
inline constexpr bool isPowerOfTwo(size_t size)
|
||||
{
|
||||
return size && !(size & (size - 1));
|
||||
}
|
||||
|
||||
template<typename T> inline T roundUpToMultipleOf(size_t divisor, T x)
|
||||
{
|
||||
BASSERT(isPowerOfTwo(divisor));
|
||||
return reinterpret_cast<T>((reinterpret_cast<uintptr_t>(x) + (divisor - 1)) & ~(divisor - 1));
|
||||
}
|
||||
|
||||
template<size_t divisor, typename T> inline constexpr T roundUpToMultipleOf(T x)
|
||||
{
|
||||
static_assert(isPowerOfTwo(divisor), "'divisor' must be a power of two.");
|
||||
return roundUpToMultipleOf(divisor, x);
|
||||
}
|
||||
|
||||
template<typename T> inline T roundDownToMultipleOf(size_t divisor, T x)
|
||||
{
|
||||
BASSERT(isPowerOfTwo(divisor));
|
||||
return reinterpret_cast<T>(mask(reinterpret_cast<uintptr_t>(x), ~(divisor - 1ul)));
|
||||
}
|
||||
|
||||
template<size_t divisor, typename T> inline constexpr T roundDownToMultipleOf(T x)
|
||||
{
|
||||
static_assert(isPowerOfTwo(divisor), "'divisor' must be a power of two.");
|
||||
return roundDownToMultipleOf(divisor, x);
|
||||
}
|
||||
|
||||
template<typename T> inline void divideRoundingUp(T numerator, T denominator, T& quotient, T& remainder)
|
||||
{
|
||||
// We expect the compiler to emit a single divide instruction to extract both the quotient and the remainder.
|
||||
quotient = numerator / denominator;
|
||||
remainder = numerator % denominator;
|
||||
if (remainder)
|
||||
quotient += 1;
|
||||
}
|
||||
|
||||
template<typename T> inline T divideRoundingUp(T numerator, T denominator)
|
||||
{
|
||||
return (numerator + denominator - 1) / denominator;
|
||||
}
|
||||
|
||||
template<typename T> inline T roundUpToMultipleOfNonPowerOfTwo(size_t divisor, T x)
|
||||
{
|
||||
return divideRoundingUp(x, divisor) * divisor;
|
||||
}
|
||||
|
||||
// Version of sizeof that returns 0 for empty classes.
|
||||
|
||||
template<typename T> inline constexpr size_t sizeOf()
|
||||
{
|
||||
return std::is_empty<T>::value ? 0 : sizeof(T);
|
||||
}
|
||||
|
||||
template<typename T> inline constexpr size_t bitCount()
|
||||
{
|
||||
return sizeof(T) * 8;
|
||||
}
|
||||
|
||||
inline constexpr unsigned long log2(unsigned long value)
|
||||
{
|
||||
return bitCount<unsigned long>() - 1 - __builtin_clzl(value);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Algorithm_h
|
216
bmalloc/Allocator.cpp
Normal file
216
bmalloc/Allocator.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "BAssert.h"
|
||||
#include "Chunk.h"
|
||||
#include "Deallocator.h"
|
||||
#include "Heap.h"
|
||||
#include "PerProcess.h"
|
||||
#include "Sizes.h"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
Allocator::Allocator(Heap* heap, Deallocator& deallocator)
|
||||
: m_isBmallocEnabled(heap->environment().isBmallocEnabled())
|
||||
, m_deallocator(deallocator)
|
||||
{
|
||||
for (size_t sizeClass = 0; sizeClass < sizeClassCount; ++sizeClass)
|
||||
m_bumpAllocators[sizeClass].init(objectSize(sizeClass));
|
||||
}
|
||||
|
||||
Allocator::~Allocator()
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
|
||||
void* Allocator::tryAllocate(size_t size)
|
||||
{
|
||||
if (!m_isBmallocEnabled)
|
||||
return malloc(size);
|
||||
|
||||
if (size <= smallMax)
|
||||
return allocate(size);
|
||||
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
return PerProcess<Heap>::getFastCase()->tryAllocateLarge(lock, alignment, size);
|
||||
}
|
||||
|
||||
void* Allocator::allocate(size_t alignment, size_t size)
|
||||
{
|
||||
bool crashOnFailure = true;
|
||||
return allocateImpl(alignment, size, crashOnFailure);
|
||||
}
|
||||
|
||||
void* Allocator::tryAllocate(size_t alignment, size_t size)
|
||||
{
|
||||
bool crashOnFailure = false;
|
||||
return allocateImpl(alignment, size, crashOnFailure);
|
||||
}
|
||||
|
||||
void* Allocator::allocateImpl(size_t alignment, size_t size, bool crashOnFailure)
|
||||
{
|
||||
BASSERT(isPowerOfTwo(alignment));
|
||||
|
||||
if (!m_isBmallocEnabled) {
|
||||
void* result = nullptr;
|
||||
if (posix_memalign(&result, alignment, size)) {
|
||||
if (crashOnFailure)
|
||||
BCRASH();
|
||||
return nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!size)
|
||||
size = alignment;
|
||||
|
||||
if (size <= smallMax && alignment <= smallMax)
|
||||
return allocate(roundUpToMultipleOf(alignment, size));
|
||||
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
Heap* heap = PerProcess<Heap>::getFastCase();
|
||||
if (crashOnFailure)
|
||||
return heap->allocateLarge(lock, alignment, size);
|
||||
return heap->tryAllocateLarge(lock, alignment, size);
|
||||
}
|
||||
|
||||
void* Allocator::reallocate(void* object, size_t newSize)
|
||||
{
|
||||
if (!m_isBmallocEnabled) {
|
||||
void* result = realloc(object, newSize);
|
||||
if (!result)
|
||||
BCRASH();
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t oldSize = 0;
|
||||
switch (objectType(object)) {
|
||||
case ObjectType::Small: {
|
||||
BASSERT(objectType(nullptr) == ObjectType::Small);
|
||||
if (!object)
|
||||
break;
|
||||
|
||||
size_t sizeClass = Object(object).page()->sizeClass();
|
||||
oldSize = objectSize(sizeClass);
|
||||
break;
|
||||
}
|
||||
case ObjectType::Large: {
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
oldSize = PerProcess<Heap>::getFastCase()->largeSize(lock, object);
|
||||
|
||||
if (newSize < oldSize && newSize > smallMax) {
|
||||
PerProcess<Heap>::getFastCase()->shrinkLarge(lock, Range(object, oldSize), newSize);
|
||||
return object;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void* result = allocate(newSize);
|
||||
size_t copySize = std::min(oldSize, newSize);
|
||||
memcpy(result, object, copySize);
|
||||
m_deallocator.deallocate(object);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Allocator::scavenge()
|
||||
{
|
||||
for (size_t sizeClass = 0; sizeClass < sizeClassCount; ++sizeClass) {
|
||||
BumpAllocator& allocator = m_bumpAllocators[sizeClass];
|
||||
BumpRangeCache& bumpRangeCache = m_bumpRangeCaches[sizeClass];
|
||||
|
||||
while (allocator.canAllocate())
|
||||
m_deallocator.deallocate(allocator.allocate());
|
||||
|
||||
while (bumpRangeCache.size()) {
|
||||
allocator.refill(bumpRangeCache.pop());
|
||||
while (allocator.canAllocate())
|
||||
m_deallocator.deallocate(allocator.allocate());
|
||||
}
|
||||
|
||||
allocator.clear();
|
||||
}
|
||||
}
|
||||
|
||||
NO_INLINE void Allocator::refillAllocatorSlowCase(BumpAllocator& allocator, size_t sizeClass)
|
||||
{
|
||||
BumpRangeCache& bumpRangeCache = m_bumpRangeCaches[sizeClass];
|
||||
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
m_deallocator.processObjectLog(lock);
|
||||
PerProcess<Heap>::getFastCase()->allocateSmallBumpRanges(lock, sizeClass, allocator, bumpRangeCache);
|
||||
}
|
||||
|
||||
INLINE void Allocator::refillAllocator(BumpAllocator& allocator, size_t sizeClass)
|
||||
{
|
||||
BumpRangeCache& bumpRangeCache = m_bumpRangeCaches[sizeClass];
|
||||
if (!bumpRangeCache.size())
|
||||
return refillAllocatorSlowCase(allocator, sizeClass);
|
||||
return allocator.refill(bumpRangeCache.pop());
|
||||
}
|
||||
|
||||
NO_INLINE void* Allocator::allocateLarge(size_t size)
|
||||
{
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
return PerProcess<Heap>::getFastCase()->allocateLarge(lock, alignment, size);
|
||||
}
|
||||
|
||||
NO_INLINE void* Allocator::allocateLogSizeClass(size_t size)
|
||||
{
|
||||
size_t sizeClass = bmalloc::sizeClass(size);
|
||||
BumpAllocator& allocator = m_bumpAllocators[sizeClass];
|
||||
if (!allocator.canAllocate())
|
||||
refillAllocator(allocator, sizeClass);
|
||||
return allocator.allocate();
|
||||
}
|
||||
|
||||
void* Allocator::allocateSlowCase(size_t size)
|
||||
{
|
||||
if (!m_isBmallocEnabled) {
|
||||
void* result = malloc(size);
|
||||
if (!result)
|
||||
BCRASH();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (size <= maskSizeClassMax) {
|
||||
size_t sizeClass = bmalloc::maskSizeClass(size);
|
||||
BumpAllocator& allocator = m_bumpAllocators[sizeClass];
|
||||
refillAllocator(allocator, sizeClass);
|
||||
return allocator.allocate();
|
||||
}
|
||||
|
||||
if (size <= smallMax)
|
||||
return allocateLogSizeClass(size);
|
||||
|
||||
return allocateLarge(size);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
94
bmalloc/Allocator.h
Normal file
94
bmalloc/Allocator.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Allocator_h
|
||||
#define Allocator_h
|
||||
|
||||
#include "BumpAllocator.h"
|
||||
#include <array>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Deallocator;
|
||||
class Heap;
|
||||
|
||||
// Per-cache object allocator.
|
||||
|
||||
class Allocator {
|
||||
public:
|
||||
Allocator(Heap*, Deallocator&);
|
||||
~Allocator();
|
||||
|
||||
void* tryAllocate(size_t);
|
||||
void* allocate(size_t);
|
||||
void* tryAllocate(size_t alignment, size_t);
|
||||
void* allocate(size_t alignment, size_t);
|
||||
void* reallocate(void*, size_t);
|
||||
|
||||
void scavenge();
|
||||
|
||||
private:
|
||||
void* allocateImpl(size_t alignment, size_t, bool crashOnFailure);
|
||||
|
||||
bool allocateFastCase(size_t, void*&);
|
||||
void* allocateSlowCase(size_t);
|
||||
|
||||
void* allocateLogSizeClass(size_t);
|
||||
void* allocateLarge(size_t);
|
||||
|
||||
void refillAllocator(BumpAllocator&, size_t sizeClass);
|
||||
void refillAllocatorSlowCase(BumpAllocator&, size_t sizeClass);
|
||||
|
||||
std::array<BumpAllocator, sizeClassCount> m_bumpAllocators;
|
||||
std::array<BumpRangeCache, sizeClassCount> m_bumpRangeCaches;
|
||||
|
||||
bool m_isBmallocEnabled;
|
||||
Deallocator& m_deallocator;
|
||||
};
|
||||
|
||||
inline bool Allocator::allocateFastCase(size_t size, void*& object)
|
||||
{
|
||||
if (size > maskSizeClassMax)
|
||||
return false;
|
||||
|
||||
BumpAllocator& allocator = m_bumpAllocators[maskSizeClass(size)];
|
||||
if (!allocator.canAllocate())
|
||||
return false;
|
||||
|
||||
object = allocator.allocate();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void* Allocator::allocate(size_t size)
|
||||
{
|
||||
void* object;
|
||||
if (!allocateFastCase(size, object))
|
||||
return allocateSlowCase(size);
|
||||
return object;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Allocator_h
|
137
bmalloc/AsyncTask.h
Normal file
137
bmalloc/AsyncTask.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef AsyncTask_h
|
||||
#define AsyncTask_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "Inline.h"
|
||||
#include "Mutex.h"
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
template<typename Object, typename Function>
|
||||
class AsyncTask {
|
||||
public:
|
||||
AsyncTask(Object&, const Function&);
|
||||
~AsyncTask();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
enum State { Sleeping, Running, RunRequested };
|
||||
|
||||
void runSlowCase();
|
||||
|
||||
static void threadEntryPoint(AsyncTask*);
|
||||
void threadRunLoop();
|
||||
|
||||
std::atomic<State> m_state;
|
||||
|
||||
Mutex m_conditionMutex;
|
||||
std::condition_variable_any m_condition;
|
||||
|
||||
std::thread m_thread;
|
||||
|
||||
Object& m_object;
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
template<typename Object, typename Function>
|
||||
AsyncTask<Object, Function>::AsyncTask(Object& object, const Function& function)
|
||||
: m_state(Running)
|
||||
, m_condition()
|
||||
, m_thread(std::thread(&AsyncTask::threadEntryPoint, this))
|
||||
, m_object(object)
|
||||
, m_function(function)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Object, typename Function>
|
||||
AsyncTask<Object, Function>::~AsyncTask()
|
||||
{
|
||||
// We'd like to mark our destructor deleted but C++ won't allow it because
|
||||
// we are an automatic member of Heap.
|
||||
RELEASE_BASSERT(0);
|
||||
}
|
||||
|
||||
template<typename Object, typename Function>
|
||||
inline void AsyncTask<Object, Function>::run()
|
||||
{
|
||||
if (m_state == RunRequested)
|
||||
return;
|
||||
runSlowCase();
|
||||
}
|
||||
|
||||
template<typename Object, typename Function>
|
||||
NO_INLINE void AsyncTask<Object, Function>::runSlowCase()
|
||||
{
|
||||
State oldState = m_state.exchange(RunRequested);
|
||||
if (oldState == RunRequested || oldState == Running)
|
||||
return;
|
||||
|
||||
BASSERT(oldState == Sleeping);
|
||||
std::lock_guard<Mutex> lock(m_conditionMutex);
|
||||
m_condition.notify_all();
|
||||
}
|
||||
|
||||
template<typename Object, typename Function>
|
||||
void AsyncTask<Object, Function>::threadEntryPoint(AsyncTask* asyncTask)
|
||||
{
|
||||
#if BOS(DARWIN)
|
||||
pthread_set_qos_class_self_np(QOS_CLASS_USER_INTERACTIVE, 0);
|
||||
#endif
|
||||
|
||||
asyncTask->threadRunLoop();
|
||||
}
|
||||
|
||||
template<typename Object, typename Function>
|
||||
void AsyncTask<Object, Function>::threadRunLoop()
|
||||
{
|
||||
// This loop ratchets downward from most active to least active state. While
|
||||
// we ratchet downward, any other thread may reset our state.
|
||||
|
||||
// We require any state change while we are sleeping to signal to our
|
||||
// condition variable and wake us up.
|
||||
|
||||
while (1) {
|
||||
State expectedState = RunRequested;
|
||||
if (m_state.compare_exchange_weak(expectedState, Running))
|
||||
(m_object.*m_function)();
|
||||
|
||||
expectedState = Running;
|
||||
if (m_state.compare_exchange_weak(expectedState, Sleeping)) {
|
||||
std::unique_lock<Mutex> lock(m_conditionMutex);
|
||||
m_condition.wait(lock, [&]() { return m_state != Sleeping; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // AsyncTask_h
|
109
bmalloc/BAssert.h
Normal file
109
bmalloc/BAssert.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BPlatform.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#if BUSE(OS_LOG)
|
||||
#include <os/log.h>
|
||||
#endif
|
||||
|
||||
#if defined(NDEBUG) && BOS(DARWIN)
|
||||
|
||||
#if BCPU(X86_64) || BCPU(X86)
|
||||
#define BBreakpointTrap() __asm__ volatile ("int3")
|
||||
#elif BCPU(ARM_THUMB2)
|
||||
#define BBreakpointTrap() __asm__ volatile ("bkpt #0")
|
||||
#elif BCPU(ARM64)
|
||||
#define BBreakpointTrap() __asm__ volatile ("brk #0")
|
||||
#else
|
||||
#error "Unsupported CPU".
|
||||
#endif
|
||||
|
||||
// Crash with a SIGTRAP i.e EXC_BREAKPOINT.
|
||||
// We are not using __builtin_trap because it is only guaranteed to abort, but not necessarily
|
||||
// trigger a SIGTRAP. Instead, we use inline asm to ensure that we trigger the SIGTRAP.
|
||||
#define BCRASH() do { \
|
||||
BBreakpointTrap(); \
|
||||
__builtin_unreachable(); \
|
||||
} while (false)
|
||||
|
||||
#else // not defined(NDEBUG) && BOS(DARWIN)
|
||||
|
||||
#define BCRASH() do { \
|
||||
*(int*)0xbbadbeef = 0; \
|
||||
} while (0);
|
||||
|
||||
#endif // defined(NDEBUG) && BOS(DARWIN)
|
||||
|
||||
#define BASSERT_IMPL(x) do { \
|
||||
if (!(x)) \
|
||||
BCRASH(); \
|
||||
} while (0);
|
||||
|
||||
#define RELEASE_BASSERT(x) BASSERT_IMPL(x)
|
||||
|
||||
#if BUSE(OS_LOG)
|
||||
#define BMALLOC_LOGGING_PREFIX "bmalloc: "
|
||||
#define BLOG_ERROR(format, ...) os_log_error(OS_LOG_DEFAULT, BMALLOC_LOGGING_PREFIX format, __VA_ARGS__)
|
||||
#else
|
||||
#define BLOG_ERROR(format, ...) bmalloc::reportAssertionFailureWithMessage(__FILE__, __LINE__, __PRETTY_FUNCTION__, format, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if defined(NDEBUG)
|
||||
#define RELEASE_BASSERT_WITH_MESSAGE(x, format, ...) BASSERT_IMPL(x)
|
||||
#else
|
||||
#define RELEASE_BASSERT_WITH_MESSAGE(x, format, ...) do { \
|
||||
if (!(x)) { \
|
||||
BLOG_ERROR("ASSERTION FAILED: " #x " :: " format, ##__VA_ARGS__); \
|
||||
BCRASH(); \
|
||||
} \
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
#define UNUSED(x) ((void)x)
|
||||
|
||||
// ===== Release build =====
|
||||
|
||||
#if defined(NDEBUG)
|
||||
|
||||
#define BASSERT(x)
|
||||
|
||||
#define IF_DEBUG(x)
|
||||
|
||||
#endif // defined(NDEBUG)
|
||||
|
||||
|
||||
// ===== Debug build =====
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
|
||||
#define BASSERT(x) BASSERT_IMPL(x)
|
||||
|
||||
#define IF_DEBUG(x) (x)
|
||||
|
||||
#endif // !defined(NDEBUG)
|
196
bmalloc/BPlatform.h
Normal file
196
bmalloc/BPlatform.h
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Availability.h>
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#define BPLATFORM(PLATFORM) (defined BPLATFORM_##PLATFORM && BPLATFORM_##PLATFORM)
|
||||
#define BOS(OS) (defined BOS_##OS && BOS_##OS)
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define BOS_DARWIN 1
|
||||
#endif
|
||||
|
||||
#ifdef __unix
|
||||
#define BOS_UNIX 1
|
||||
#endif
|
||||
|
||||
#if BOS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) \
|
||||
|| (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \
|
||||
|| (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR))
|
||||
#define BPLATFORM_IOS 1
|
||||
#elif BOS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC
|
||||
#define BPLATFORM_MAC 1
|
||||
#endif
|
||||
|
||||
/* ==== Policy decision macros: these define policy choices for a particular port. ==== */
|
||||
|
||||
/* BUSE() - use a particular third-party library or optional OS service */
|
||||
#define BUSE(FEATURE) (defined BUSE_##FEATURE && BUSE_##FEATURE)
|
||||
|
||||
/* ==== Platform adaptation macros: these describe properties of the target environment. ==== */
|
||||
|
||||
/* BCPU() - the target CPU architecture */
|
||||
#define BCPU(_FEATURE) (defined BCPU_##_FEATURE && BCPU_##_FEATURE)
|
||||
|
||||
/* BCPU(X86) - i386 / x86 32-bit */
|
||||
#if defined(__i386__) \
|
||||
|| defined(i386) \
|
||||
|| defined(_M_IX86) \
|
||||
|| defined(_X86_) \
|
||||
|| defined(__THW_INTEL)
|
||||
#define BCPU_X86 1
|
||||
#endif
|
||||
|
||||
/* BCPU(X86_64) - AMD64 / Intel64 / x86_64 64-bit */
|
||||
#if defined(__x86_64__) \
|
||||
|| defined(_M_X64)
|
||||
#define BCPU_X86_64 1
|
||||
#endif
|
||||
|
||||
/* BCPU(ARM64) - Apple */
|
||||
#if (defined(__arm64__) && defined(__APPLE__)) || defined(__aarch64__)
|
||||
#define BCPU_ARM64 1
|
||||
#endif
|
||||
|
||||
/* BCPU(ARM) - ARM, any version*/
|
||||
#define BARM_ARCH_AT_LEAST(N) (BCPU(ARM) && BARM_ARCH_VERSION >= N)
|
||||
|
||||
#if defined(arm) \
|
||||
|| defined(__arm__) \
|
||||
|| defined(ARM) \
|
||||
|| defined(_ARM_)
|
||||
#define BCPU_ARM 1
|
||||
|
||||
/* Set BARM_ARCH_VERSION */
|
||||
#if defined(__ARM_ARCH_4__) \
|
||||
|| defined(__ARM_ARCH_4T__) \
|
||||
|| defined(__MARM_ARMV4__)
|
||||
#define BARM_ARCH_VERSION 4
|
||||
|
||||
#elif defined(__ARM_ARCH_5__) \
|
||||
|| defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__MARM_ARMV5__)
|
||||
#define BARM_ARCH_VERSION 5
|
||||
|
||||
#elif defined(__ARM_ARCH_5E__) \
|
||||
|| defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
#define BARM_ARCH_VERSION 5
|
||||
|
||||
#elif defined(__ARM_ARCH_6__) \
|
||||
|| defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) \
|
||||
|| defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__) \
|
||||
|| defined(__ARM_ARCH_6T2__) \
|
||||
|| defined(__ARMV6__)
|
||||
#define BARM_ARCH_VERSION 6
|
||||
|
||||
#elif defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7K__) \
|
||||
|| defined(__ARM_ARCH_7R__) \
|
||||
|| defined(__ARM_ARCH_7S__)
|
||||
#define BARM_ARCH_VERSION 7
|
||||
|
||||
#elif defined(__ARM_ARCH_8__)
|
||||
#define BARM_ARCH_VERSION 8
|
||||
|
||||
/* MSVC sets _M_ARM */
|
||||
#elif defined(_M_ARM)
|
||||
#define BARM_ARCH_VERSION _M_ARM
|
||||
|
||||
/* RVCT sets _TARGET_ARCH_ARM */
|
||||
#elif defined(__TARGET_ARCH_ARM)
|
||||
#define BARM_ARCH_VERSION __TARGET_ARCH_ARM
|
||||
|
||||
#else
|
||||
#define WTF_ARM_ARCH_VERSION 0
|
||||
|
||||
#endif
|
||||
|
||||
/* Set BTHUMB_ARCH_VERSION */
|
||||
#if defined(__ARM_ARCH_4T__)
|
||||
#define BTHUMB_ARCH_VERSION 1
|
||||
|
||||
#elif defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
#define BTHUMB_ARCH_VERSION 2
|
||||
|
||||
#elif defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) \
|
||||
|| defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__) \
|
||||
|| defined(__ARM_ARCH_6M__)
|
||||
#define BTHUMB_ARCH_VERSION 3
|
||||
|
||||
#elif defined(__ARM_ARCH_6T2__) \
|
||||
|| defined(__ARM_ARCH_7__) \
|
||||
|| defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7K__) \
|
||||
|| defined(__ARM_ARCH_7M__) \
|
||||
|| defined(__ARM_ARCH_7R__) \
|
||||
|| defined(__ARM_ARCH_7S__)
|
||||
#define BTHUMB_ARCH_VERSION 4
|
||||
|
||||
/* RVCT sets __TARGET_ARCH_THUMB */
|
||||
#elif defined(__TARGET_ARCH_THUMB)
|
||||
#define BTHUMB_ARCH_VERSION __TARGET_ARCH_THUMB
|
||||
|
||||
#else
|
||||
#define BTHUMB_ARCH_VERSION 0
|
||||
#endif
|
||||
|
||||
/* BCPU(ARM_TRADITIONAL) - Thumb2 is not available, only traditional ARM (v4 or greater) */
|
||||
/* BCPU(ARM_THUMB2) - Thumb2 instruction set is available */
|
||||
/* Only one of these will be defined. */
|
||||
#if !defined(BCPU_ARM_TRADITIONAL) && !defined(BCPU_ARM_THUMB2)
|
||||
# if defined(thumb2) || defined(__thumb2__) \
|
||||
|| ((defined(__thumb) || defined(__thumb__)) && BTHUMB_ARCH_VERSION == 4)
|
||||
# define BCPU_ARM_TRADITIONAL 0
|
||||
# define BCPU_ARM_THUMB2 1
|
||||
# elif BARM_ARCH_AT_LEAST(4)
|
||||
# define BCPU_ARM_TRADITIONAL 1
|
||||
# define BCPU_ARM_THUMB2 0
|
||||
# else
|
||||
# error "Not supported ARM architecture"
|
||||
# endif
|
||||
#elif BCPU(ARM_TRADITIONAL) && BCPU(ARM_THUMB2) /* Sanity Check */
|
||||
# error "Cannot use both of BCPU_ARM_TRADITIONAL and BCPU_ARM_THUMB2 platforms"
|
||||
#endif /* !defined(BCPU_ARM_TRADITIONAL) && !defined(BCPU_ARM_THUMB2) */
|
||||
|
||||
#endif /* ARM */
|
||||
|
||||
#define BATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
|
||||
|
||||
#if (BPLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (BPLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
|
||||
#define BUSE_OS_LOG 1
|
||||
#endif
|
98
bmalloc/BumpAllocator.h
Normal file
98
bmalloc/BumpAllocator.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BumpAllocator_h
|
||||
#define BumpAllocator_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "BumpRange.h"
|
||||
#include "ObjectType.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// Helper object for allocating small objects.
|
||||
|
||||
class BumpAllocator {
|
||||
public:
|
||||
BumpAllocator();
|
||||
void init(size_t);
|
||||
|
||||
size_t size() { return m_size; }
|
||||
|
||||
bool isNull() { return !m_ptr; }
|
||||
void clear();
|
||||
|
||||
bool canAllocate() { return !!m_remaining; }
|
||||
void* allocate();
|
||||
|
||||
void refill(const BumpRange&);
|
||||
|
||||
private:
|
||||
char* m_ptr;
|
||||
unsigned m_size;
|
||||
unsigned m_remaining;
|
||||
};
|
||||
|
||||
inline BumpAllocator::BumpAllocator()
|
||||
: m_ptr()
|
||||
, m_size()
|
||||
, m_remaining()
|
||||
{
|
||||
}
|
||||
|
||||
inline void BumpAllocator::init(size_t size)
|
||||
{
|
||||
m_ptr = nullptr;
|
||||
m_size = size;
|
||||
m_remaining = 0;
|
||||
}
|
||||
|
||||
inline void* BumpAllocator::allocate()
|
||||
{
|
||||
BASSERT(m_remaining);
|
||||
|
||||
--m_remaining;
|
||||
char* result = m_ptr;
|
||||
m_ptr += m_size;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void BumpAllocator::refill(const BumpRange& bumpRange)
|
||||
{
|
||||
BASSERT(!canAllocate());
|
||||
m_ptr = bumpRange.begin;
|
||||
m_remaining = bumpRange.objectCount;
|
||||
BASSERT(canAllocate());
|
||||
}
|
||||
|
||||
inline void BumpAllocator::clear()
|
||||
{
|
||||
m_ptr = nullptr;
|
||||
m_remaining = 0;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // BumpAllocator_h
|
44
bmalloc/BumpRange.h
Normal file
44
bmalloc/BumpRange.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BumpRange_h
|
||||
#define BumpRange_h
|
||||
|
||||
#include "FixedVector.h"
|
||||
#include "Range.h"
|
||||
#include "Sizes.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
struct BumpRange {
|
||||
char* begin;
|
||||
unsigned short objectCount;
|
||||
};
|
||||
|
||||
typedef FixedVector<BumpRange, bumpRangeCacheCapacity> BumpRangeCache;
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // BumpRange_h
|
84
bmalloc/Cache.cpp
Normal file
84
bmalloc/Cache.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Heap.h"
|
||||
#include "Inline.h"
|
||||
#include "PerProcess.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
void* Cache::operator new(size_t size)
|
||||
{
|
||||
return vmAllocate(vmSize(size));
|
||||
}
|
||||
|
||||
void Cache::operator delete(void* p, size_t size)
|
||||
{
|
||||
vmDeallocate(p, vmSize(size));
|
||||
}
|
||||
|
||||
void Cache::scavenge()
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
cache->allocator().scavenge();
|
||||
cache->deallocator().scavenge();
|
||||
}
|
||||
|
||||
Cache::Cache()
|
||||
: m_deallocator(PerProcess<Heap>::get())
|
||||
, m_allocator(PerProcess<Heap>::get(), m_deallocator)
|
||||
{
|
||||
}
|
||||
|
||||
NO_INLINE void* Cache::tryAllocateSlowCaseNullCache(size_t size)
|
||||
{
|
||||
return PerThread<Cache>::getSlowCase()->allocator().tryAllocate(size);
|
||||
}
|
||||
|
||||
NO_INLINE void* Cache::allocateSlowCaseNullCache(size_t size)
|
||||
{
|
||||
return PerThread<Cache>::getSlowCase()->allocator().allocate(size);
|
||||
}
|
||||
|
||||
NO_INLINE void* Cache::allocateSlowCaseNullCache(size_t alignment, size_t size)
|
||||
{
|
||||
return PerThread<Cache>::getSlowCase()->allocator().allocate(alignment, size);
|
||||
}
|
||||
|
||||
NO_INLINE void Cache::deallocateSlowCaseNullCache(void* object)
|
||||
{
|
||||
PerThread<Cache>::getSlowCase()->deallocator().deallocate(object);
|
||||
}
|
||||
|
||||
NO_INLINE void* Cache::reallocateSlowCaseNullCache(void* object, size_t newSize)
|
||||
{
|
||||
return PerThread<Cache>::getSlowCase()->allocator().reallocate(object, newSize);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
117
bmalloc/Cache.h
Normal file
117
bmalloc/Cache.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Cache_h
|
||||
#define Cache_h
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "Deallocator.h"
|
||||
#include "PerThread.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// Per-thread allocation / deallocation cache, backed by a per-process Heap.
|
||||
|
||||
class Cache {
|
||||
public:
|
||||
void* operator new(size_t);
|
||||
void operator delete(void*, size_t);
|
||||
|
||||
static void* tryAllocate(size_t);
|
||||
static void* allocate(size_t);
|
||||
static void* tryAllocate(size_t alignment, size_t);
|
||||
static void* allocate(size_t alignment, size_t);
|
||||
static void deallocate(void*);
|
||||
static void* reallocate(void*, size_t);
|
||||
|
||||
static void scavenge();
|
||||
|
||||
Cache();
|
||||
|
||||
Allocator& allocator() { return m_allocator; }
|
||||
Deallocator& deallocator() { return m_deallocator; }
|
||||
|
||||
private:
|
||||
static void* tryAllocateSlowCaseNullCache(size_t);
|
||||
static void* allocateSlowCaseNullCache(size_t);
|
||||
static void* allocateSlowCaseNullCache(size_t alignment, size_t);
|
||||
static void deallocateSlowCaseNullCache(void*);
|
||||
static void* reallocateSlowCaseNullCache(void*, size_t);
|
||||
|
||||
Deallocator m_deallocator;
|
||||
Allocator m_allocator;
|
||||
};
|
||||
|
||||
inline void* Cache::tryAllocate(size_t size)
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return tryAllocateSlowCaseNullCache(size);
|
||||
return cache->allocator().tryAllocate(size);
|
||||
}
|
||||
|
||||
inline void* Cache::allocate(size_t size)
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return allocateSlowCaseNullCache(size);
|
||||
return cache->allocator().allocate(size);
|
||||
}
|
||||
|
||||
inline void* Cache::tryAllocate(size_t alignment, size_t size)
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return allocateSlowCaseNullCache(alignment, size);
|
||||
return cache->allocator().tryAllocate(alignment, size);
|
||||
}
|
||||
|
||||
inline void* Cache::allocate(size_t alignment, size_t size)
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return allocateSlowCaseNullCache(alignment, size);
|
||||
return cache->allocator().allocate(alignment, size);
|
||||
}
|
||||
|
||||
inline void Cache::deallocate(void* object)
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return deallocateSlowCaseNullCache(object);
|
||||
return cache->deallocator().deallocate(object);
|
||||
}
|
||||
|
||||
inline void* Cache::reallocate(void* object, size_t newSize)
|
||||
{
|
||||
Cache* cache = PerThread<Cache>::getFastCase();
|
||||
if (!cache)
|
||||
return reallocateSlowCaseNullCache(object, newSize);
|
||||
return cache->allocator().reallocate(object, newSize);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Cache_h
|
153
bmalloc/Chunk.h
Normal file
153
bmalloc/Chunk.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Chunk_h
|
||||
#define Chunk_h
|
||||
|
||||
#include "Object.h"
|
||||
#include "Sizes.h"
|
||||
#include "SmallLine.h"
|
||||
#include "SmallPage.h"
|
||||
#include "VMAllocate.h"
|
||||
#include <array>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
static Chunk* get(void*);
|
||||
|
||||
Chunk(std::lock_guard<StaticMutex>&);
|
||||
|
||||
size_t offset(void*);
|
||||
|
||||
char* address(size_t offset);
|
||||
SmallPage* page(size_t offset);
|
||||
SmallLine* line(size_t offset);
|
||||
|
||||
char* bytes() { return reinterpret_cast<char*>(this); }
|
||||
SmallLine* lines() { return &m_lines[0]; }
|
||||
SmallPage* pages() { return &m_pages[0]; }
|
||||
|
||||
private:
|
||||
std::array<SmallLine, chunkSize / smallLineSize> m_lines;
|
||||
std::array<SmallPage, chunkSize / smallPageSize> m_pages;
|
||||
};
|
||||
|
||||
struct ChunkHash {
|
||||
static unsigned hash(Chunk* key)
|
||||
{
|
||||
return static_cast<unsigned>(
|
||||
reinterpret_cast<uintptr_t>(key) / chunkSize);
|
||||
}
|
||||
};
|
||||
|
||||
inline Chunk::Chunk(std::lock_guard<StaticMutex>&)
|
||||
{
|
||||
}
|
||||
|
||||
inline Chunk* Chunk::get(void* address)
|
||||
{
|
||||
return static_cast<Chunk*>(mask(address, chunkMask));
|
||||
}
|
||||
|
||||
inline size_t Chunk::offset(void* address)
|
||||
{
|
||||
BASSERT(address >= this);
|
||||
BASSERT(address < bytes() + chunkSize);
|
||||
return static_cast<char*>(address) - bytes();
|
||||
}
|
||||
|
||||
inline char* Chunk::address(size_t offset)
|
||||
{
|
||||
return bytes() + offset;
|
||||
}
|
||||
|
||||
inline SmallPage* Chunk::page(size_t offset)
|
||||
{
|
||||
size_t pageNumber = offset / smallPageSize;
|
||||
SmallPage* page = &m_pages[pageNumber];
|
||||
return page - page->slide();
|
||||
}
|
||||
|
||||
inline SmallLine* Chunk::line(size_t offset)
|
||||
{
|
||||
size_t lineNumber = offset / smallLineSize;
|
||||
return &m_lines[lineNumber];
|
||||
}
|
||||
|
||||
inline char* SmallLine::begin()
|
||||
{
|
||||
Chunk* chunk = Chunk::get(this);
|
||||
size_t lineNumber = this - chunk->lines();
|
||||
size_t offset = lineNumber * smallLineSize;
|
||||
return &reinterpret_cast<char*>(chunk)[offset];
|
||||
}
|
||||
|
||||
inline char* SmallLine::end()
|
||||
{
|
||||
return begin() + smallLineSize;
|
||||
}
|
||||
|
||||
inline SmallLine* SmallPage::begin()
|
||||
{
|
||||
BASSERT(!m_slide);
|
||||
Chunk* chunk = Chunk::get(this);
|
||||
size_t pageNumber = this - chunk->pages();
|
||||
size_t lineNumber = pageNumber * smallPageLineCount;
|
||||
return &chunk->lines()[lineNumber];
|
||||
}
|
||||
|
||||
inline Object::Object(void* object)
|
||||
: m_chunk(Chunk::get(object))
|
||||
, m_offset(m_chunk->offset(object))
|
||||
{
|
||||
}
|
||||
|
||||
inline Object::Object(Chunk* chunk, void* object)
|
||||
: m_chunk(chunk)
|
||||
, m_offset(m_chunk->offset(object))
|
||||
{
|
||||
BASSERT(chunk == Chunk::get(object));
|
||||
}
|
||||
|
||||
inline char* Object::address()
|
||||
{
|
||||
return m_chunk->address(m_offset);
|
||||
}
|
||||
|
||||
inline SmallLine* Object::line()
|
||||
{
|
||||
return m_chunk->line(m_offset);
|
||||
}
|
||||
|
||||
inline SmallPage* Object::page()
|
||||
{
|
||||
return m_chunk->page(m_offset);
|
||||
}
|
||||
|
||||
}; // namespace bmalloc
|
||||
|
||||
#endif // Chunk
|
100
bmalloc/Deallocator.cpp
Normal file
100
bmalloc/Deallocator.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "Chunk.h"
|
||||
#include "Deallocator.h"
|
||||
#include "Heap.h"
|
||||
#include "Inline.h"
|
||||
#include "Object.h"
|
||||
#include "PerProcess.h"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <sys/mman.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
Deallocator::Deallocator(Heap* heap)
|
||||
: m_isBmallocEnabled(heap->environment().isBmallocEnabled())
|
||||
{
|
||||
if (!m_isBmallocEnabled) {
|
||||
// Fill the object log in order to disable the fast path.
|
||||
while (m_objectLog.size() != m_objectLog.capacity())
|
||||
m_objectLog.push(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Deallocator::~Deallocator()
|
||||
{
|
||||
scavenge();
|
||||
}
|
||||
|
||||
void Deallocator::scavenge()
|
||||
{
|
||||
if (m_isBmallocEnabled)
|
||||
processObjectLog();
|
||||
}
|
||||
|
||||
void Deallocator::processObjectLog(std::lock_guard<StaticMutex>& lock)
|
||||
{
|
||||
Heap* heap = PerProcess<Heap>::getFastCase();
|
||||
|
||||
for (Object object : m_objectLog)
|
||||
heap->derefSmallLine(lock, object);
|
||||
|
||||
m_objectLog.clear();
|
||||
}
|
||||
|
||||
void Deallocator::processObjectLog()
|
||||
{
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
processObjectLog(lock);
|
||||
}
|
||||
|
||||
void Deallocator::deallocateSlowCase(void* object)
|
||||
{
|
||||
if (!m_isBmallocEnabled) {
|
||||
free(object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!object)
|
||||
return;
|
||||
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
if (PerProcess<Heap>::getFastCase()->isLarge(lock, object)) {
|
||||
PerProcess<Heap>::getFastCase()->deallocateLarge(lock, object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_objectLog.size() == m_objectLog.capacity())
|
||||
processObjectLog(lock);
|
||||
|
||||
m_objectLog.push(object);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
79
bmalloc/Deallocator.h
Normal file
79
bmalloc/Deallocator.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Deallocator_h
|
||||
#define Deallocator_h
|
||||
|
||||
#include "FixedVector.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Heap;
|
||||
class StaticMutex;
|
||||
|
||||
// Per-cache object deallocator.
|
||||
|
||||
class Deallocator {
|
||||
public:
|
||||
Deallocator(Heap*);
|
||||
~Deallocator();
|
||||
|
||||
void deallocate(void*);
|
||||
void scavenge();
|
||||
|
||||
void processObjectLog();
|
||||
void processObjectLog(std::lock_guard<StaticMutex>&);
|
||||
|
||||
private:
|
||||
bool deallocateFastCase(void*);
|
||||
void deallocateSlowCase(void*);
|
||||
|
||||
FixedVector<void*, deallocatorLogCapacity> m_objectLog;
|
||||
bool m_isBmallocEnabled;
|
||||
};
|
||||
|
||||
inline bool Deallocator::deallocateFastCase(void* object)
|
||||
{
|
||||
BASSERT(mightBeLarge(nullptr));
|
||||
if (mightBeLarge(object))
|
||||
return false;
|
||||
|
||||
if (m_objectLog.size() == m_objectLog.capacity())
|
||||
return false;
|
||||
|
||||
m_objectLog.push(object);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Deallocator::deallocate(void* object)
|
||||
{
|
||||
if (!deallocateFastCase(object))
|
||||
deallocateSlowCase(object);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Deallocator_h
|
126
bmalloc/Environment.cpp
Normal file
126
bmalloc/Environment.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "BPlatform.h"
|
||||
#include "Environment.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#if BOS(DARWIN)
|
||||
#include <mach-o/dyld.h>
|
||||
#elif BOS(UNIX)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
static bool isMallocEnvironmentVariableSet()
|
||||
{
|
||||
const char* list[] = {
|
||||
"Malloc",
|
||||
"MallocLogFile",
|
||||
"MallocGuardEdges",
|
||||
"MallocDoNotProtectPrelude",
|
||||
"MallocDoNotProtectPostlude",
|
||||
"MallocStackLogging",
|
||||
"MallocStackLoggingNoCompact",
|
||||
"MallocStackLoggingDirectory",
|
||||
"MallocScribble",
|
||||
"MallocCheckHeapStart",
|
||||
"MallocCheckHeapEach",
|
||||
"MallocCheckHeapSleep",
|
||||
"MallocCheckHeapAbort",
|
||||
"MallocErrorAbort",
|
||||
"MallocCorruptionAbort",
|
||||
"MallocHelp"
|
||||
};
|
||||
size_t size = sizeof(list) / sizeof(const char*);
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (getenv(list[i]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isLibgmallocEnabled()
|
||||
{
|
||||
char* variable = getenv("DYLD_INSERT_LIBRARIES");
|
||||
if (!variable)
|
||||
return false;
|
||||
if (!strstr(variable, "libgmalloc"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isSanitizerEnabled()
|
||||
{
|
||||
#if BOS(DARWIN)
|
||||
static const char sanitizerPrefix[] = "/libclang_rt.";
|
||||
static const char asanName[] = "asan_";
|
||||
static const char tsanName[] = "tsan_";
|
||||
uint32_t imageCount = _dyld_image_count();
|
||||
for (uint32_t i = 0; i < imageCount; ++i) {
|
||||
const char* imageName = _dyld_get_image_name(i);
|
||||
if (!imageName)
|
||||
continue;
|
||||
if (const char* s = strstr(imageName, sanitizerPrefix)) {
|
||||
const char* sanitizerName = s + sizeof(sanitizerPrefix) - 1;
|
||||
if (!strncmp(sanitizerName, asanName, sizeof(asanName) - 1))
|
||||
return true;
|
||||
if (!strncmp(sanitizerName, tsanName, sizeof(tsanName) - 1))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#elif BOS(UNIX)
|
||||
void* handle = dlopen(nullptr, RTLD_NOW);
|
||||
if (!handle)
|
||||
return false;
|
||||
bool result = !!dlsym(handle, "__asan_init") || !!dlsym(handle, "__tsan_init");
|
||||
dlclose(handle);
|
||||
return result;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
Environment::Environment()
|
||||
: m_isBmallocEnabled(computeIsBmallocEnabled())
|
||||
{
|
||||
}
|
||||
|
||||
bool Environment::computeIsBmallocEnabled()
|
||||
{
|
||||
if (isMallocEnvironmentVariableSet())
|
||||
return false;
|
||||
if (isLibgmallocEnabled())
|
||||
return false;
|
||||
if (isSanitizerEnabled())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
45
bmalloc/Environment.h
Normal file
45
bmalloc/Environment.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Environment_h
|
||||
#define Environment_h
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Environment {
|
||||
public:
|
||||
Environment();
|
||||
|
||||
bool isBmallocEnabled() { return m_isBmallocEnabled; }
|
||||
|
||||
private:
|
||||
bool computeIsBmallocEnabled();
|
||||
|
||||
bool m_isBmallocEnabled;
|
||||
};
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Environment_h
|
119
bmalloc/FixedVector.h
Normal file
119
bmalloc/FixedVector.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FixedVector_h
|
||||
#define FixedVector_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// A replacement for std::vector that uses a fixed-sized inline backing store.
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
class FixedVector {
|
||||
static_assert(std::is_trivially_destructible<T>::value, "FixedVector must have a trivial destructor.");
|
||||
public:
|
||||
FixedVector(const FixedVector&) = delete;
|
||||
FixedVector& operator=(const FixedVector&) = delete;
|
||||
|
||||
FixedVector();
|
||||
|
||||
const T* begin() const { return &m_buffer[0]; }
|
||||
const T* end() const { return begin() + size(); }
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
size_t capacity() const { return Capacity; }
|
||||
|
||||
T& operator[](size_t);
|
||||
|
||||
void push(const T&);
|
||||
void push(const T*, const T*);
|
||||
T pop();
|
||||
|
||||
void shrink(T*);
|
||||
void shrink(size_t);
|
||||
|
||||
void clear() { shrink(static_cast<size_t>(0)); }
|
||||
bool isEmpty() { return !m_size; }
|
||||
|
||||
private:
|
||||
size_t m_size;
|
||||
std::array<T, Capacity> m_buffer;
|
||||
};
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline FixedVector<T, Capacity>::FixedVector()
|
||||
: m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline T& FixedVector<T, Capacity>::operator[](size_t i)
|
||||
{
|
||||
BASSERT(i < m_size);
|
||||
return m_buffer[i];
|
||||
}
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline void FixedVector<T, Capacity>::push(const T& value)
|
||||
{
|
||||
BASSERT(m_size < Capacity);
|
||||
m_buffer[m_size++] = value;
|
||||
}
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline void FixedVector<T, Capacity>::push(const T* begin, const T* end)
|
||||
{
|
||||
for (const T* it = begin; it != end; ++it)
|
||||
push(*it);
|
||||
}
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline T FixedVector<T, Capacity>::pop()
|
||||
{
|
||||
BASSERT(m_size);
|
||||
return m_buffer[--m_size];
|
||||
}
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline void FixedVector<T, Capacity>::shrink(size_t size)
|
||||
{
|
||||
BASSERT(size <= m_size);
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
template<typename T, size_t Capacity>
|
||||
inline void FixedVector<T, Capacity>::shrink(T* end)
|
||||
{
|
||||
shrink(end - begin());
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // FixedVector_h
|
415
bmalloc/Heap.cpp
Normal file
415
bmalloc/Heap.cpp
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Heap.h"
|
||||
#include "BumpAllocator.h"
|
||||
#include "Chunk.h"
|
||||
#include "PerProcess.h"
|
||||
#include "SmallLine.h"
|
||||
#include "SmallPage.h"
|
||||
#include <thread>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
Heap::Heap(std::lock_guard<StaticMutex>&)
|
||||
: m_vmPageSizePhysical(vmPageSizePhysical())
|
||||
, m_isAllocatingPages(false)
|
||||
, m_scavenger(*this, &Heap::concurrentScavenge)
|
||||
{
|
||||
RELEASE_BASSERT(vmPageSizePhysical() >= smallPageSize);
|
||||
RELEASE_BASSERT(vmPageSize() >= vmPageSizePhysical());
|
||||
|
||||
initializeLineMetadata();
|
||||
initializePageMetadata();
|
||||
}
|
||||
|
||||
void Heap::initializeLineMetadata()
|
||||
{
|
||||
size_t sizeClassCount = bmalloc::sizeClass(smallLineSize);
|
||||
size_t smallLineCount = m_vmPageSizePhysical / smallLineSize;
|
||||
m_smallLineMetadata.grow(sizeClassCount * smallLineCount);
|
||||
|
||||
for (size_t sizeClass = 0; sizeClass < sizeClassCount; ++sizeClass) {
|
||||
size_t size = objectSize(sizeClass);
|
||||
LineMetadata* pageMetadata = &m_smallLineMetadata[sizeClass * smallLineCount];
|
||||
|
||||
size_t object = 0;
|
||||
size_t line = 0;
|
||||
while (object < m_vmPageSizePhysical) {
|
||||
line = object / smallLineSize;
|
||||
size_t leftover = object % smallLineSize;
|
||||
|
||||
size_t objectCount;
|
||||
size_t remainder;
|
||||
divideRoundingUp(smallLineSize - leftover, size, objectCount, remainder);
|
||||
|
||||
pageMetadata[line] = { static_cast<unsigned char>(leftover), static_cast<unsigned char>(objectCount) };
|
||||
|
||||
object += objectCount * size;
|
||||
}
|
||||
|
||||
// Don't allow the last object in a page to escape the page.
|
||||
if (object > m_vmPageSizePhysical) {
|
||||
BASSERT(pageMetadata[line].objectCount);
|
||||
--pageMetadata[line].objectCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::initializePageMetadata()
|
||||
{
|
||||
auto computePageSize = [&](size_t sizeClass) {
|
||||
size_t size = objectSize(sizeClass);
|
||||
if (sizeClass < bmalloc::sizeClass(smallLineSize))
|
||||
return m_vmPageSizePhysical;
|
||||
|
||||
for (size_t pageSize = m_vmPageSizePhysical;
|
||||
pageSize < pageSizeMax;
|
||||
pageSize += m_vmPageSizePhysical) {
|
||||
RELEASE_BASSERT(pageSize <= chunkSize / 2);
|
||||
size_t waste = pageSize % size;
|
||||
if (waste <= pageSize / pageSizeWasteFactor)
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
return pageSizeMax;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeClassCount; ++i)
|
||||
m_pageClasses[i] = (computePageSize(i) - 1) / smallPageSize;
|
||||
}
|
||||
|
||||
void Heap::concurrentScavenge()
|
||||
{
|
||||
std::unique_lock<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
|
||||
#if BOS(DARWIN)
|
||||
if (auto requestedQOSClass = PerProcess<Heap>::getFastCase()->takeRequestedScavengerThreadQOSClass())
|
||||
pthread_set_qos_class_self_np(requestedQOSClass, 0);
|
||||
#endif
|
||||
|
||||
scavenge(lock, scavengeSleepDuration);
|
||||
}
|
||||
|
||||
void Heap::scavenge(std::unique_lock<StaticMutex>& lock, std::chrono::milliseconds sleepDuration)
|
||||
{
|
||||
waitUntilFalse(lock, sleepDuration, m_isAllocatingPages);
|
||||
|
||||
scavengeSmallPages(lock, sleepDuration);
|
||||
scavengeLargeObjects(lock, sleepDuration);
|
||||
|
||||
sleep(lock, sleepDuration);
|
||||
}
|
||||
|
||||
void Heap::scavengeSmallPages(std::unique_lock<StaticMutex>& lock, std::chrono::milliseconds sleepDuration)
|
||||
{
|
||||
for (auto& smallPages : m_smallPages) {
|
||||
while (!smallPages.isEmpty()) {
|
||||
SmallPage* page = smallPages.pop();
|
||||
size_t pageClass = m_pageClasses[page->sizeClass()];
|
||||
m_vmHeap.deallocateSmallPage(lock, pageClass, page);
|
||||
waitUntilFalse(lock, sleepDuration, m_isAllocatingPages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::scavengeLargeObjects(std::unique_lock<StaticMutex>& lock, std::chrono::milliseconds sleepDuration)
|
||||
{
|
||||
auto& ranges = m_largeFree.ranges();
|
||||
for (size_t i = ranges.size(); i-- > 0; i = std::min(i, ranges.size())) {
|
||||
auto range = ranges.pop(i);
|
||||
|
||||
lock.unlock();
|
||||
vmDeallocatePhysicalPagesSloppy(range.begin(), range.size());
|
||||
lock.lock();
|
||||
|
||||
range.setPhysicalSize(0);
|
||||
ranges.push(range);
|
||||
|
||||
waitUntilFalse(lock, sleepDuration, m_isAllocatingPages);
|
||||
}
|
||||
}
|
||||
|
||||
SmallPage* Heap::allocateSmallPage(std::lock_guard<StaticMutex>& lock, size_t sizeClass)
|
||||
{
|
||||
if (!m_smallPagesWithFreeLines[sizeClass].isEmpty())
|
||||
return m_smallPagesWithFreeLines[sizeClass].popFront();
|
||||
|
||||
SmallPage* page = [&]() {
|
||||
size_t pageClass = m_pageClasses[sizeClass];
|
||||
if (!m_smallPages[pageClass].isEmpty())
|
||||
return m_smallPages[pageClass].pop();
|
||||
|
||||
m_isAllocatingPages = true;
|
||||
|
||||
SmallPage* page = m_vmHeap.allocateSmallPage(lock, pageClass);
|
||||
m_objectTypes.set(Chunk::get(page), ObjectType::Small);
|
||||
return page;
|
||||
}();
|
||||
|
||||
page->setSizeClass(sizeClass);
|
||||
return page;
|
||||
}
|
||||
|
||||
void Heap::deallocateSmallLine(std::lock_guard<StaticMutex>& lock, Object object)
|
||||
{
|
||||
BASSERT(!object.line()->refCount(lock));
|
||||
SmallPage* page = object.page();
|
||||
page->deref(lock);
|
||||
|
||||
if (!page->hasFreeLines(lock)) {
|
||||
page->setHasFreeLines(lock, true);
|
||||
m_smallPagesWithFreeLines[page->sizeClass()].push(page);
|
||||
}
|
||||
|
||||
if (page->refCount(lock))
|
||||
return;
|
||||
|
||||
size_t sizeClass = page->sizeClass();
|
||||
size_t pageClass = m_pageClasses[sizeClass];
|
||||
|
||||
m_smallPagesWithFreeLines[sizeClass].remove(page);
|
||||
m_smallPages[pageClass].push(page);
|
||||
|
||||
m_scavenger.run();
|
||||
}
|
||||
|
||||
void Heap::allocateSmallBumpRangesByMetadata(
|
||||
std::lock_guard<StaticMutex>& lock, size_t sizeClass,
|
||||
BumpAllocator& allocator, BumpRangeCache& rangeCache)
|
||||
{
|
||||
SmallPage* page = allocateSmallPage(lock, sizeClass);
|
||||
SmallLine* lines = page->begin();
|
||||
BASSERT(page->hasFreeLines(lock));
|
||||
size_t smallLineCount = m_vmPageSizePhysical / smallLineSize;
|
||||
LineMetadata* pageMetadata = &m_smallLineMetadata[sizeClass * smallLineCount];
|
||||
|
||||
auto findSmallBumpRange = [&](size_t& lineNumber) {
|
||||
for ( ; lineNumber < smallLineCount; ++lineNumber) {
|
||||
if (!lines[lineNumber].refCount(lock)) {
|
||||
if (pageMetadata[lineNumber].objectCount)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto allocateSmallBumpRange = [&](size_t& lineNumber) -> BumpRange {
|
||||
char* begin = lines[lineNumber].begin() + pageMetadata[lineNumber].startOffset;
|
||||
unsigned short objectCount = 0;
|
||||
|
||||
for ( ; lineNumber < smallLineCount; ++lineNumber) {
|
||||
if (lines[lineNumber].refCount(lock))
|
||||
break;
|
||||
|
||||
if (!pageMetadata[lineNumber].objectCount)
|
||||
continue;
|
||||
|
||||
objectCount += pageMetadata[lineNumber].objectCount;
|
||||
lines[lineNumber].ref(lock, pageMetadata[lineNumber].objectCount);
|
||||
page->ref(lock);
|
||||
}
|
||||
return { begin, objectCount };
|
||||
};
|
||||
|
||||
size_t lineNumber = 0;
|
||||
for (;;) {
|
||||
if (!findSmallBumpRange(lineNumber)) {
|
||||
page->setHasFreeLines(lock, false);
|
||||
BASSERT(allocator.canAllocate());
|
||||
return;
|
||||
}
|
||||
|
||||
// In a fragmented page, some free ranges might not fit in the cache.
|
||||
if (rangeCache.size() == rangeCache.capacity()) {
|
||||
m_smallPagesWithFreeLines[sizeClass].push(page);
|
||||
BASSERT(allocator.canAllocate());
|
||||
return;
|
||||
}
|
||||
|
||||
BumpRange bumpRange = allocateSmallBumpRange(lineNumber);
|
||||
if (allocator.canAllocate())
|
||||
rangeCache.push(bumpRange);
|
||||
else
|
||||
allocator.refill(bumpRange);
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::allocateSmallBumpRangesByObject(
|
||||
std::lock_guard<StaticMutex>& lock, size_t sizeClass,
|
||||
BumpAllocator& allocator, BumpRangeCache& rangeCache)
|
||||
{
|
||||
size_t size = allocator.size();
|
||||
SmallPage* page = allocateSmallPage(lock, sizeClass);
|
||||
BASSERT(page->hasFreeLines(lock));
|
||||
|
||||
auto findSmallBumpRange = [&](Object& it, Object& end) {
|
||||
for ( ; it + size <= end; it = it + size) {
|
||||
if (!it.line()->refCount(lock))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto allocateSmallBumpRange = [&](Object& it, Object& end) -> BumpRange {
|
||||
char* begin = it.address();
|
||||
unsigned short objectCount = 0;
|
||||
for ( ; it + size <= end; it = it + size) {
|
||||
if (it.line()->refCount(lock))
|
||||
break;
|
||||
|
||||
++objectCount;
|
||||
it.line()->ref(lock);
|
||||
it.page()->ref(lock);
|
||||
}
|
||||
return { begin, objectCount };
|
||||
};
|
||||
|
||||
Object it(page->begin()->begin());
|
||||
Object end(it + pageSize(m_pageClasses[sizeClass]));
|
||||
for (;;) {
|
||||
if (!findSmallBumpRange(it, end)) {
|
||||
page->setHasFreeLines(lock, false);
|
||||
BASSERT(allocator.canAllocate());
|
||||
return;
|
||||
}
|
||||
|
||||
// In a fragmented page, some free ranges might not fit in the cache.
|
||||
if (rangeCache.size() == rangeCache.capacity()) {
|
||||
m_smallPagesWithFreeLines[sizeClass].push(page);
|
||||
BASSERT(allocator.canAllocate());
|
||||
return;
|
||||
}
|
||||
|
||||
BumpRange bumpRange = allocateSmallBumpRange(it, end);
|
||||
if (allocator.canAllocate())
|
||||
rangeCache.push(bumpRange);
|
||||
else
|
||||
allocator.refill(bumpRange);
|
||||
}
|
||||
}
|
||||
|
||||
LargeRange Heap::splitAndAllocate(LargeRange& range, size_t alignment, size_t size)
|
||||
{
|
||||
LargeRange prev;
|
||||
LargeRange next;
|
||||
|
||||
size_t alignmentMask = alignment - 1;
|
||||
if (test(range.begin(), alignmentMask)) {
|
||||
size_t prefixSize = roundUpToMultipleOf(alignment, range.begin()) - range.begin();
|
||||
std::pair<LargeRange, LargeRange> pair = range.split(prefixSize);
|
||||
prev = pair.first;
|
||||
range = pair.second;
|
||||
}
|
||||
|
||||
if (range.size() - size > size / pageSizeWasteFactor) {
|
||||
std::pair<LargeRange, LargeRange> pair = range.split(size);
|
||||
range = pair.first;
|
||||
next = pair.second;
|
||||
}
|
||||
|
||||
if (range.physicalSize() < range.size()) {
|
||||
m_isAllocatingPages = true;
|
||||
|
||||
vmAllocatePhysicalPagesSloppy(range.begin() + range.physicalSize(), range.size() - range.physicalSize());
|
||||
range.setPhysicalSize(range.size());
|
||||
}
|
||||
|
||||
if (prev)
|
||||
m_largeFree.add(prev);
|
||||
|
||||
if (next)
|
||||
m_largeFree.add(next);
|
||||
|
||||
m_objectTypes.set(Chunk::get(range.begin()), ObjectType::Large);
|
||||
|
||||
m_largeAllocated.set(range.begin(), range.size());
|
||||
return range;
|
||||
}
|
||||
|
||||
void* Heap::tryAllocateLarge(std::lock_guard<StaticMutex>& lock, size_t alignment, size_t size)
|
||||
{
|
||||
BASSERT(isPowerOfTwo(alignment));
|
||||
|
||||
size_t roundedSize = size ? roundUpToMultipleOf(largeAlignment, size) : largeAlignment;
|
||||
if (roundedSize < size) // Check for overflow
|
||||
return nullptr;
|
||||
size = roundedSize;
|
||||
|
||||
size_t roundedAlignment = roundUpToMultipleOf<largeAlignment>(alignment);
|
||||
if (roundedAlignment < alignment) // Check for overflow
|
||||
return nullptr;
|
||||
alignment = roundedAlignment;
|
||||
|
||||
LargeRange range = m_largeFree.remove(alignment, size);
|
||||
if (!range) {
|
||||
range = m_vmHeap.tryAllocateLargeChunk(lock, alignment, size);
|
||||
if (!range)
|
||||
return nullptr;
|
||||
|
||||
m_largeFree.add(range);
|
||||
range = m_largeFree.remove(alignment, size);
|
||||
}
|
||||
|
||||
return splitAndAllocate(range, alignment, size).begin();
|
||||
}
|
||||
|
||||
void* Heap::allocateLarge(std::lock_guard<StaticMutex>& lock, size_t alignment, size_t size)
|
||||
{
|
||||
void* result = tryAllocateLarge(lock, alignment, size);
|
||||
RELEASE_BASSERT(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Heap::isLarge(std::lock_guard<StaticMutex>&, void* object)
|
||||
{
|
||||
return m_objectTypes.get(Object(object).chunk()) == ObjectType::Large;
|
||||
}
|
||||
|
||||
size_t Heap::largeSize(std::lock_guard<StaticMutex>&, void* object)
|
||||
{
|
||||
return m_largeAllocated.get(object);
|
||||
}
|
||||
|
||||
void Heap::shrinkLarge(std::lock_guard<StaticMutex>&, const Range& object, size_t newSize)
|
||||
{
|
||||
BASSERT(object.size() > newSize);
|
||||
|
||||
size_t size = m_largeAllocated.remove(object.begin());
|
||||
LargeRange range = LargeRange(object, size);
|
||||
splitAndAllocate(range, alignment, newSize);
|
||||
|
||||
m_scavenger.run();
|
||||
}
|
||||
|
||||
void Heap::deallocateLarge(std::lock_guard<StaticMutex>&, void* object)
|
||||
{
|
||||
size_t size = m_largeAllocated.remove(object);
|
||||
m_largeFree.add(LargeRange(object, size, size));
|
||||
|
||||
m_scavenger.run();
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
150
bmalloc/Heap.h
Normal file
150
bmalloc/Heap.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Heap_h
|
||||
#define Heap_h
|
||||
|
||||
#include "AsyncTask.h"
|
||||
#include "BumpRange.h"
|
||||
#include "Environment.h"
|
||||
#include "LargeMap.h"
|
||||
#include "LineMetadata.h"
|
||||
#include "List.h"
|
||||
#include "Map.h"
|
||||
#include "Mutex.h"
|
||||
#include "Object.h"
|
||||
#include "SmallLine.h"
|
||||
#include "SmallPage.h"
|
||||
#include "VMHeap.h"
|
||||
#include "Vector.h"
|
||||
#include <array>
|
||||
#include <mutex>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class BeginTag;
|
||||
class BumpAllocator;
|
||||
class EndTag;
|
||||
|
||||
class Heap {
|
||||
public:
|
||||
Heap(std::lock_guard<StaticMutex>&);
|
||||
|
||||
Environment& environment() { return m_environment; }
|
||||
|
||||
void allocateSmallBumpRanges(std::lock_guard<StaticMutex>&, size_t sizeClass, BumpAllocator&, BumpRangeCache&);
|
||||
void derefSmallLine(std::lock_guard<StaticMutex>&, Object);
|
||||
|
||||
void* allocateLarge(std::lock_guard<StaticMutex>&, size_t alignment, size_t);
|
||||
void* tryAllocateLarge(std::lock_guard<StaticMutex>&, size_t alignment, size_t);
|
||||
void deallocateLarge(std::lock_guard<StaticMutex>&, void*);
|
||||
|
||||
bool isLarge(std::lock_guard<StaticMutex>&, void*);
|
||||
size_t largeSize(std::lock_guard<StaticMutex>&, void*);
|
||||
void shrinkLarge(std::lock_guard<StaticMutex>&, const Range&, size_t);
|
||||
|
||||
void scavenge(std::unique_lock<StaticMutex>&, std::chrono::milliseconds sleepDuration);
|
||||
|
||||
#if BOS(DARWIN)
|
||||
qos_class_t takeRequestedScavengerThreadQOSClass() { return std::exchange(m_requestedScavengerThreadQOSClass, QOS_CLASS_UNSPECIFIED); }
|
||||
void setScavengerThreadQOSClass(qos_class_t overrideClass) { m_requestedScavengerThreadQOSClass = overrideClass; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
struct LargeObjectHash {
|
||||
static unsigned hash(void* key)
|
||||
{
|
||||
return static_cast<unsigned>(
|
||||
reinterpret_cast<uintptr_t>(key) / smallMax);
|
||||
}
|
||||
};
|
||||
|
||||
~Heap() = delete;
|
||||
|
||||
void initializeLineMetadata();
|
||||
void initializePageMetadata();
|
||||
|
||||
void allocateSmallBumpRangesByMetadata(std::lock_guard<StaticMutex>&,
|
||||
size_t sizeClass, BumpAllocator&, BumpRangeCache&);
|
||||
void allocateSmallBumpRangesByObject(std::lock_guard<StaticMutex>&,
|
||||
size_t sizeClass, BumpAllocator&, BumpRangeCache&);
|
||||
|
||||
SmallPage* allocateSmallPage(std::lock_guard<StaticMutex>&, size_t sizeClass);
|
||||
|
||||
void deallocateSmallLine(std::lock_guard<StaticMutex>&, Object);
|
||||
|
||||
void mergeLarge(BeginTag*&, EndTag*&, Range&);
|
||||
void mergeLargeLeft(EndTag*&, BeginTag*&, Range&, bool& inVMHeap);
|
||||
void mergeLargeRight(EndTag*&, BeginTag*&, Range&, bool& inVMHeap);
|
||||
|
||||
LargeRange splitAndAllocate(LargeRange&, size_t alignment, size_t);
|
||||
|
||||
void concurrentScavenge();
|
||||
void scavengeSmallPages(std::unique_lock<StaticMutex>&, std::chrono::milliseconds);
|
||||
void scavengeLargeObjects(std::unique_lock<StaticMutex>&, std::chrono::milliseconds);
|
||||
|
||||
size_t m_vmPageSizePhysical;
|
||||
Vector<LineMetadata> m_smallLineMetadata;
|
||||
std::array<size_t, sizeClassCount> m_pageClasses;
|
||||
|
||||
std::array<List<SmallPage>, sizeClassCount> m_smallPagesWithFreeLines;
|
||||
std::array<List<SmallPage>, pageClassCount> m_smallPages;
|
||||
|
||||
Map<void*, size_t, LargeObjectHash> m_largeAllocated;
|
||||
LargeMap m_largeFree;
|
||||
|
||||
Map<Chunk*, ObjectType, ChunkHash> m_objectTypes;
|
||||
|
||||
bool m_isAllocatingPages;
|
||||
AsyncTask<Heap, decltype(&Heap::concurrentScavenge)> m_scavenger;
|
||||
|
||||
Environment m_environment;
|
||||
|
||||
VMHeap m_vmHeap;
|
||||
|
||||
#if BOS(DARWIN)
|
||||
qos_class_t m_requestedScavengerThreadQOSClass { QOS_CLASS_UNSPECIFIED };
|
||||
#endif
|
||||
};
|
||||
|
||||
inline void Heap::allocateSmallBumpRanges(
|
||||
std::lock_guard<StaticMutex>& lock, size_t sizeClass,
|
||||
BumpAllocator& allocator, BumpRangeCache& rangeCache)
|
||||
{
|
||||
if (sizeClass < bmalloc::sizeClass(smallLineSize))
|
||||
return allocateSmallBumpRangesByMetadata(lock, sizeClass, allocator, rangeCache);
|
||||
return allocateSmallBumpRangesByObject(lock, sizeClass, allocator, rangeCache);
|
||||
}
|
||||
|
||||
inline void Heap::derefSmallLine(std::lock_guard<StaticMutex>& lock, Object object)
|
||||
{
|
||||
if (!object.line()->deref(lock))
|
||||
return;
|
||||
deallocateSmallLine(lock, object);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Heap_h
|
33
bmalloc/Inline.h
Normal file
33
bmalloc/Inline.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Inline_h
|
||||
#define Inline_h
|
||||
|
||||
#define INLINE __attribute__((always_inline)) inline
|
||||
|
||||
#define NO_INLINE __attribute__((noinline))
|
||||
|
||||
#endif // Inline_h
|
79
bmalloc/LargeMap.cpp
Normal file
79
bmalloc/LargeMap.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "LargeMap.h"
|
||||
#include <utility>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
LargeRange LargeMap::remove(size_t alignment, size_t size)
|
||||
{
|
||||
size_t alignmentMask = alignment - 1;
|
||||
|
||||
LargeRange* candidate = m_free.end();
|
||||
for (LargeRange* it = m_free.begin(); it != m_free.end(); ++it) {
|
||||
if (it->size() < size)
|
||||
continue;
|
||||
|
||||
if (candidate != m_free.end() && candidate->begin() < it->begin())
|
||||
continue;
|
||||
|
||||
if (test(it->begin(), alignmentMask)) {
|
||||
char* aligned = roundUpToMultipleOf(alignment, it->begin());
|
||||
if (aligned < it->begin()) // Check for overflow.
|
||||
continue;
|
||||
|
||||
char* alignedEnd = aligned + size;
|
||||
if (alignedEnd < aligned) // Check for overflow.
|
||||
continue;
|
||||
|
||||
if (alignedEnd > it->end())
|
||||
continue;
|
||||
}
|
||||
|
||||
candidate = it;
|
||||
}
|
||||
|
||||
if (candidate == m_free.end())
|
||||
return LargeRange();
|
||||
|
||||
return m_free.pop(candidate);
|
||||
}
|
||||
|
||||
void LargeMap::add(const LargeRange& range)
|
||||
{
|
||||
LargeRange merged = range;
|
||||
|
||||
for (size_t i = 0; i < m_free.size(); ++i) {
|
||||
if (!canMerge(merged, m_free[i]))
|
||||
continue;
|
||||
|
||||
merged = merge(merged, m_free.pop(i--));
|
||||
}
|
||||
|
||||
m_free.push(merged);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
47
bmalloc/LargeMap.h
Normal file
47
bmalloc/LargeMap.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LargeMap_h
|
||||
#define LargeMap_h
|
||||
|
||||
#include "LargeRange.h"
|
||||
#include "Vector.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class LargeMap {
|
||||
public:
|
||||
void add(const LargeRange&);
|
||||
LargeRange remove(size_t alignment, size_t);
|
||||
Vector<LargeRange>& ranges() { return m_free; }
|
||||
|
||||
private:
|
||||
Vector<LargeRange> m_free;
|
||||
};
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // LargeMap_h
|
110
bmalloc/LargeRange.h
Normal file
110
bmalloc/LargeRange.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LargeRange_h
|
||||
#define LargeRange_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "Range.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class LargeRange : public Range {
|
||||
public:
|
||||
LargeRange()
|
||||
: Range()
|
||||
, m_physicalSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
LargeRange(const Range& other, size_t physicalSize)
|
||||
: Range(other)
|
||||
, m_physicalSize(physicalSize)
|
||||
{
|
||||
}
|
||||
|
||||
LargeRange(void* begin, size_t size, size_t physicalSize)
|
||||
: Range(begin, size)
|
||||
, m_physicalSize(physicalSize)
|
||||
{
|
||||
}
|
||||
|
||||
size_t physicalSize() const { return m_physicalSize; }
|
||||
void setPhysicalSize(size_t physicalSize) { m_physicalSize = physicalSize; }
|
||||
|
||||
std::pair<LargeRange, LargeRange> split(size_t) const;
|
||||
|
||||
bool operator<(const void* other) const { return begin() < other; }
|
||||
bool operator<(const LargeRange& other) const { return begin() < other.begin(); }
|
||||
|
||||
private:
|
||||
size_t m_physicalSize;
|
||||
};
|
||||
|
||||
inline bool canMerge(const LargeRange& a, const LargeRange& b)
|
||||
{
|
||||
if (a.end() == b.begin())
|
||||
return true;
|
||||
|
||||
if (b.end() == a.begin())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline LargeRange merge(const LargeRange& a, const LargeRange& b)
|
||||
{
|
||||
const LargeRange& left = std::min(a, b);
|
||||
if (left.size() == left.physicalSize()) {
|
||||
return LargeRange(
|
||||
left.begin(),
|
||||
a.size() + b.size(),
|
||||
a.physicalSize() + b.physicalSize());
|
||||
}
|
||||
|
||||
return LargeRange(
|
||||
left.begin(),
|
||||
a.size() + b.size(),
|
||||
left.physicalSize());
|
||||
}
|
||||
|
||||
inline std::pair<LargeRange, LargeRange> LargeRange::split(size_t size) const
|
||||
{
|
||||
BASSERT(size <= this->size());
|
||||
|
||||
if (size <= physicalSize()) {
|
||||
LargeRange left(begin(), size, size);
|
||||
LargeRange right(left.end(), this->size() - size, physicalSize() - size);
|
||||
return std::make_pair(left, right);
|
||||
}
|
||||
|
||||
LargeRange left(begin(), size, physicalSize());
|
||||
LargeRange right(left.end(), this->size() - size, 0);
|
||||
return std::make_pair(left, right);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // LargeRange_h
|
46
bmalloc/LineMetadata.h
Normal file
46
bmalloc/LineMetadata.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LineMetadata_h
|
||||
#define LineMetadata_h
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
struct LineMetadata {
|
||||
unsigned char startOffset;
|
||||
unsigned char objectCount;
|
||||
};
|
||||
|
||||
static_assert(
|
||||
smallLineSize - alignment <= std::numeric_limits<unsigned char>::max(),
|
||||
"maximum object offset must fit in LineMetadata::startOffset");
|
||||
|
||||
static_assert(
|
||||
smallLineSize / alignment <= std::numeric_limits<unsigned char>::max(),
|
||||
"maximum object count must fit in LineMetadata::objectCount");
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // LineMetadata_h
|
102
bmalloc/List.h
Normal file
102
bmalloc/List.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef List_h
|
||||
#define List_h
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
template<typename T>
|
||||
struct ListNode {
|
||||
ListNode()
|
||||
: prev(this)
|
||||
, next(this)
|
||||
{
|
||||
}
|
||||
|
||||
ListNode<T>* prev;
|
||||
ListNode<T>* next;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class List {
|
||||
static_assert(std::is_trivially_destructible<T>::value, "List must have a trivial destructor.");
|
||||
public:
|
||||
bool isEmpty() { return m_root.next == &m_root; }
|
||||
|
||||
T* head() { return static_cast<T*>(m_root.next); }
|
||||
T* tail() { return static_cast<T*>(m_root.prev); }
|
||||
|
||||
void push(T* node)
|
||||
{
|
||||
ListNode<T>* it = tail();
|
||||
insertAfter(it, node);
|
||||
}
|
||||
|
||||
T* pop()
|
||||
{
|
||||
ListNode<T>* result = tail();
|
||||
remove(result);
|
||||
return static_cast<T*>(result);
|
||||
}
|
||||
|
||||
T* popFront()
|
||||
{
|
||||
ListNode<T>* result = head();
|
||||
remove(result);
|
||||
return static_cast<T*>(result);
|
||||
}
|
||||
|
||||
void insertAfter(ListNode<T>* it, ListNode<T>* node)
|
||||
{
|
||||
ListNode<T>* prev = it;
|
||||
ListNode<T>* next = it->next;
|
||||
|
||||
node->next = next;
|
||||
next->prev = node;
|
||||
|
||||
node->prev = prev;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
void remove(ListNode<T>* node)
|
||||
{
|
||||
ListNode<T>* next = node->next;
|
||||
ListNode<T>* prev = node->prev;
|
||||
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
|
||||
node->prev = node;
|
||||
node->next = node;
|
||||
}
|
||||
|
||||
private:
|
||||
ListNode<T> m_root;
|
||||
};
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // List_h
|
65
bmalloc/Logging.cpp
Normal file
65
bmalloc/Logging.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Logging.h"
|
||||
#include "BPlatform.h"
|
||||
|
||||
#if !BUSE(OS_LOG)
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if BPLATFORM(IOS)
|
||||
#include <mach/exception_types.h>
|
||||
#include <objc/objc.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "BSoftLinking.h"
|
||||
BSOFT_LINK_PRIVATE_FRAMEWORK(CrashReporterSupport);
|
||||
BSOFT_LINK_FUNCTION(CrashReporterSupport, SimulateCrash, BOOL, (pid_t pid, mach_exception_data_type_t exceptionCode, id description), (pid, exceptionCode, description));
|
||||
#endif
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
void logVMFailure()
|
||||
{
|
||||
#if BPLATFORM(IOS)
|
||||
const mach_exception_data_type_t kExceptionCode = 0xc105ca11;
|
||||
SimulateCrash(getpid(), kExceptionCode, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !BUSE(OS_LOG)
|
||||
void reportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "%s(%d) : %s\n", file, line, function);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace bmalloc
|
38
bmalloc/Logging.h
Normal file
38
bmalloc/Logging.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BPlatform.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
void logVMFailure();
|
||||
|
||||
#if !BUSE(OS_LOG)
|
||||
void reportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* format, ...) BATTRIBUTE_PRINTF(4, 5);
|
||||
#endif
|
||||
|
||||
} // namespace bmalloc
|
134
bmalloc/Map.h
Normal file
134
bmalloc/Map.h
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Map_h
|
||||
#define Map_h
|
||||
|
||||
#include "Inline.h"
|
||||
#include "Sizes.h"
|
||||
#include "Vector.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class SmallPage;
|
||||
|
||||
template<typename Key, typename Value, typename Hash> class Map {
|
||||
static_assert(std::is_trivially_destructible<Key>::value, "Map must have a trivial destructor.");
|
||||
static_assert(std::is_trivially_destructible<Value>::value, "Map must have a trivial destructor.");
|
||||
public:
|
||||
struct Bucket {
|
||||
Key key;
|
||||
Value value;
|
||||
};
|
||||
|
||||
size_t size() { return m_keyCount; }
|
||||
size_t capacity() { return m_table.size(); }
|
||||
|
||||
// key must be in the map.
|
||||
Value& get(const Key& key)
|
||||
{
|
||||
auto& bucket = find(key, [&](const Bucket& bucket) { return bucket.key == key; });
|
||||
return bucket.value;
|
||||
}
|
||||
|
||||
void set(const Key& key, const Value& value)
|
||||
{
|
||||
if (shouldGrow())
|
||||
rehash();
|
||||
|
||||
auto& bucket = find(key, [&](const Bucket& bucket) { return !bucket.key || bucket.key == key; });
|
||||
if (!bucket.key) {
|
||||
bucket.key = key;
|
||||
++m_keyCount;
|
||||
}
|
||||
bucket.value = value;
|
||||
}
|
||||
|
||||
// key must be in the map.
|
||||
Value remove(const Key& key)
|
||||
{
|
||||
if (shouldShrink())
|
||||
rehash();
|
||||
|
||||
auto& bucket = find(key, [&](const Bucket& bucket) { return bucket.key == key; });
|
||||
Value value = bucket.value;
|
||||
bucket.key = Key();
|
||||
--m_keyCount;
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
static const unsigned minCapacity = 16;
|
||||
static const unsigned maxLoad = 2;
|
||||
static const unsigned rehashLoad = 4;
|
||||
static const unsigned minLoad = 8;
|
||||
|
||||
bool shouldGrow() { return m_keyCount * maxLoad >= capacity(); }
|
||||
bool shouldShrink() { return m_keyCount * minLoad <= capacity() && capacity() > minCapacity; }
|
||||
|
||||
void rehash();
|
||||
|
||||
template<typename Predicate>
|
||||
Bucket& find(const Key& key, const Predicate& predicate)
|
||||
{
|
||||
for (unsigned h = Hash::hash(key); ; ++h) {
|
||||
unsigned i = h & m_tableMask;
|
||||
|
||||
Bucket& bucket = m_table[i];
|
||||
if (predicate(bucket))
|
||||
return bucket;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned m_keyCount;
|
||||
unsigned m_tableMask;
|
||||
Vector<Bucket> m_table;
|
||||
};
|
||||
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
void Map<Key, Value, Hash>::rehash()
|
||||
{
|
||||
auto oldTable = std::move(m_table);
|
||||
|
||||
size_t newCapacity = std::max(minCapacity, m_keyCount * rehashLoad);
|
||||
m_table.resize(newCapacity);
|
||||
|
||||
m_keyCount = 0;
|
||||
m_tableMask = newCapacity - 1;
|
||||
|
||||
for (auto& bucket : oldTable) {
|
||||
if (!bucket.key)
|
||||
continue;
|
||||
|
||||
BASSERT(!shouldGrow());
|
||||
set(bucket.key, bucket.value);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Key, typename Value, typename Hash> const unsigned Map<Key, Value, Hash>::minCapacity;
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Map_h
|
48
bmalloc/Mutex.h
Normal file
48
bmalloc/Mutex.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Mutex_h
|
||||
#define Mutex_h
|
||||
|
||||
#include "StaticMutex.h"
|
||||
|
||||
// A fast replacement for std::mutex, for use in standard storage.
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Mutex : public StaticMutex {
|
||||
public:
|
||||
Mutex();
|
||||
};
|
||||
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
// StaticMutex requires explicit initialization when used in non-static storage.
|
||||
init();
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Mutex_h
|
81
bmalloc/Object.h
Normal file
81
bmalloc/Object.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Object_h
|
||||
#define Object_h
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Chunk;
|
||||
class SmallLine;
|
||||
class SmallPage;
|
||||
|
||||
class Object {
|
||||
public:
|
||||
Object(void*);
|
||||
Object(Chunk*, void*);
|
||||
Object(Chunk* chunk, size_t offset)
|
||||
: m_chunk(chunk)
|
||||
, m_offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
Chunk* chunk() { return m_chunk; }
|
||||
size_t offset() { return m_offset; }
|
||||
char* address();
|
||||
|
||||
SmallLine* line();
|
||||
SmallPage* page();
|
||||
|
||||
Object operator+(size_t);
|
||||
Object operator-(size_t);
|
||||
bool operator<=(const Object&);
|
||||
|
||||
private:
|
||||
Chunk* m_chunk;
|
||||
size_t m_offset;
|
||||
};
|
||||
|
||||
inline Object Object::operator+(size_t offset)
|
||||
{
|
||||
return Object(m_chunk, m_offset + offset);
|
||||
}
|
||||
|
||||
inline Object Object::operator-(size_t offset)
|
||||
{
|
||||
return Object(m_chunk, m_offset - offset);
|
||||
}
|
||||
|
||||
inline bool Object::operator<=(const Object& other)
|
||||
{
|
||||
BASSERT(m_chunk == other.m_chunk);
|
||||
return m_offset <= other.m_offset;
|
||||
}
|
||||
|
||||
}; // namespace bmalloc
|
||||
|
||||
#endif // Object_h
|
49
bmalloc/ObjectType.cpp
Normal file
49
bmalloc/ObjectType.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ObjectType.h"
|
||||
|
||||
#include "Chunk.h"
|
||||
#include "Heap.h"
|
||||
#include "Object.h"
|
||||
#include "PerProcess.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
ObjectType objectType(void* object)
|
||||
{
|
||||
if (mightBeLarge(object)) {
|
||||
if (!object)
|
||||
return ObjectType::Small;
|
||||
|
||||
std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
if (PerProcess<Heap>::getFastCase()->isLarge(lock, object))
|
||||
return ObjectType::Large;
|
||||
}
|
||||
|
||||
return ObjectType::Small;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
45
bmalloc/ObjectType.h
Normal file
45
bmalloc/ObjectType.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ObjectType_h
|
||||
#define ObjectType_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "Sizes.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
enum class ObjectType : unsigned char { Small, Large };
|
||||
|
||||
ObjectType objectType(void*);
|
||||
|
||||
inline bool mightBeLarge(void* object)
|
||||
{
|
||||
return !test(object, largeAlignmentMask);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // ObjectType_h
|
110
bmalloc/PerProcess.h
Normal file
110
bmalloc/PerProcess.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PerProcess_h
|
||||
#define PerProcess_h
|
||||
|
||||
#include "Inline.h"
|
||||
#include "Sizes.h"
|
||||
#include "StaticMutex.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// Usage:
|
||||
// Object* object = PerProcess<Object>::get();
|
||||
// x = object->field->field;
|
||||
//
|
||||
// Object will be instantiated only once, even in the face of concurrency.
|
||||
//
|
||||
// NOTE: If you observe global side-effects of the Object constructor, be
|
||||
// sure to lock the Object mutex. For example:
|
||||
//
|
||||
// Object() : m_field(...) { globalFlag = true }
|
||||
//
|
||||
// Object* object = PerProcess<Object>::get();
|
||||
// x = object->m_field; // OK
|
||||
// if (gobalFlag) { ... } // Undefined behavior.
|
||||
//
|
||||
// std::lock_guard<StaticMutex> lock(PerProcess<Object>::mutex());
|
||||
// Object* object = PerProcess<Object>::get(lock);
|
||||
// if (gobalFlag) { ... } // OK.
|
||||
|
||||
template<typename T>
|
||||
class PerProcess {
|
||||
public:
|
||||
static T* get();
|
||||
static T* getFastCase();
|
||||
|
||||
static StaticMutex& mutex() { return s_mutex; }
|
||||
|
||||
private:
|
||||
static T* getSlowCase();
|
||||
|
||||
static std::atomic<T*> s_object;
|
||||
static StaticMutex s_mutex;
|
||||
|
||||
typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type Memory;
|
||||
static Memory s_memory;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
INLINE T* PerProcess<T>::getFastCase()
|
||||
{
|
||||
return s_object.load(std::memory_order_consume);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE T* PerProcess<T>::get()
|
||||
{
|
||||
T* object = getFastCase();
|
||||
if (!object)
|
||||
return getSlowCase();
|
||||
return object;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NO_INLINE T* PerProcess<T>::getSlowCase()
|
||||
{
|
||||
std::lock_guard<StaticMutex> lock(s_mutex);
|
||||
if (!s_object.load(std::memory_order_consume)) {
|
||||
T* t = new (&s_memory) T(lock);
|
||||
s_object.store(t, std::memory_order_release);
|
||||
}
|
||||
return s_object.load(std::memory_order_consume);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::atomic<T*> PerProcess<T>::s_object;
|
||||
|
||||
template<typename T>
|
||||
StaticMutex PerProcess<T>::s_mutex;
|
||||
|
||||
template<typename T>
|
||||
typename PerProcess<T>::Memory PerProcess<T>::s_memory;
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // PerProcess_h
|
148
bmalloc/PerThread.h
Normal file
148
bmalloc/PerThread.h
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PerThread_h
|
||||
#define PerThread_h
|
||||
|
||||
#include "BPlatform.h"
|
||||
#include "Inline.h"
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<System/pthread_machdep.h>)
|
||||
#include <System/pthread_machdep.h>
|
||||
#define HAVE_PTHREAD_MACHDEP_H 1
|
||||
#else
|
||||
#define HAVE_PTHREAD_MACHDEP_H 0
|
||||
#endif
|
||||
#else
|
||||
#define HAVE_PTHREAD_MACHDEP_H 0
|
||||
#endif
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// Usage:
|
||||
// Object* object = PerThread<Object>::get();
|
||||
|
||||
template<typename T>
|
||||
class PerThread {
|
||||
public:
|
||||
static T* get();
|
||||
static T* getFastCase();
|
||||
static T* getSlowCase();
|
||||
|
||||
private:
|
||||
static void destructor(void*);
|
||||
};
|
||||
|
||||
#if HAVE_PTHREAD_MACHDEP_H
|
||||
|
||||
class Cache;
|
||||
template<typename T> struct PerThreadStorage;
|
||||
|
||||
// For now, we only support PerThread<Cache>. We can expand to other types by
|
||||
// using more keys.
|
||||
template<> struct PerThreadStorage<Cache> {
|
||||
static const pthread_key_t key = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0;
|
||||
|
||||
static void* get()
|
||||
{
|
||||
return _pthread_getspecific_direct(key);
|
||||
}
|
||||
|
||||
static void init(void* object, void (*destructor)(void*))
|
||||
{
|
||||
_pthread_setspecific_direct(key, object);
|
||||
pthread_key_init_np(key, destructor);
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename T> struct PerThreadStorage {
|
||||
static bool s_didInitialize;
|
||||
static pthread_key_t s_key;
|
||||
static std::once_flag s_onceFlag;
|
||||
|
||||
static void* get()
|
||||
{
|
||||
if (!s_didInitialize)
|
||||
return nullptr;
|
||||
return pthread_getspecific(s_key);
|
||||
}
|
||||
|
||||
static void init(void* object, void (*destructor)(void*))
|
||||
{
|
||||
std::call_once(s_onceFlag, [destructor]() {
|
||||
int error = pthread_key_create(&s_key, destructor);
|
||||
if (error)
|
||||
BCRASH();
|
||||
s_didInitialize = true;
|
||||
});
|
||||
pthread_setspecific(s_key, object);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> bool PerThreadStorage<T>::s_didInitialize;
|
||||
template<typename T> pthread_key_t PerThreadStorage<T>::s_key;
|
||||
template<typename T> std::once_flag PerThreadStorage<T>::s_onceFlag;
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
INLINE T* PerThread<T>::getFastCase()
|
||||
{
|
||||
return static_cast<T*>(PerThreadStorage<T>::get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T* PerThread<T>::get()
|
||||
{
|
||||
T* t = getFastCase();
|
||||
if (!t)
|
||||
return getSlowCase();
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void PerThread<T>::destructor(void* p)
|
||||
{
|
||||
T* t = static_cast<T*>(p);
|
||||
delete t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* PerThread<T>::getSlowCase()
|
||||
{
|
||||
BASSERT(!getFastCase());
|
||||
T* t = new T;
|
||||
PerThreadStorage<T>::init(t, destructor);
|
||||
return t;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // PerThread_h
|
73
bmalloc/Range.h
Normal file
73
bmalloc/Range.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Range_h
|
||||
#define Range_h
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Range {
|
||||
public:
|
||||
Range()
|
||||
: m_begin(0)
|
||||
, m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
Range(void* start, size_t size)
|
||||
: m_begin(static_cast<char*>(start))
|
||||
, m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
char* begin() const { return m_begin; }
|
||||
char* end() const { return m_begin + m_size; }
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
bool operator!() const { return !m_size; }
|
||||
explicit operator bool() const { return !!*this; }
|
||||
bool operator<(const Range& other) const { return m_begin < other.m_begin; }
|
||||
|
||||
private:
|
||||
char* m_begin;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
inline bool canMerge(const Range& a, const Range& b)
|
||||
{
|
||||
return a.begin() == b.end() || a.end() == b.begin();
|
||||
}
|
||||
|
||||
inline Range merge(const Range& a, const Range& b)
|
||||
{
|
||||
return Range(std::min(a.begin(), b.begin()), a.size() + b.size());
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Range_h
|
54
bmalloc/ScopeExit.h
Normal file
54
bmalloc/ScopeExit.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
template<typename ExitFunction>
|
||||
class ScopeExit {
|
||||
public:
|
||||
explicit ScopeExit(ExitFunction&& exitFunction)
|
||||
: m_exitFunction(exitFunction)
|
||||
{
|
||||
}
|
||||
|
||||
~ScopeExit()
|
||||
{
|
||||
m_exitFunction();
|
||||
}
|
||||
|
||||
private:
|
||||
ExitFunction m_exitFunction;
|
||||
};
|
||||
|
||||
template<typename ExitFunction>
|
||||
ScopeExit<ExitFunction> makeScopeExit(ExitFunction&& exitFunction)
|
||||
{
|
||||
return ScopeExit<ExitFunction>(std::forward<ExitFunction>(exitFunction));
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
130
bmalloc/Sizes.h
Normal file
130
bmalloc/Sizes.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Sizes_h
|
||||
#define Sizes_h
|
||||
|
||||
#include "Algorithm.h"
|
||||
#include "BPlatform.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <chrono>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// Repository for malloc sizing constants and calculations.
|
||||
|
||||
namespace Sizes {
|
||||
static const size_t kB = 1024;
|
||||
static const size_t MB = kB * kB;
|
||||
|
||||
static const size_t alignment = 8;
|
||||
static const size_t alignmentMask = alignment - 1ul;
|
||||
|
||||
static const size_t chunkSize = 2 * MB;
|
||||
static const size_t chunkMask = ~(chunkSize - 1ul);
|
||||
|
||||
static const size_t smallLineSize = 256;
|
||||
static const size_t smallPageSize = 4 * kB;
|
||||
static const size_t smallPageLineCount = smallPageSize / smallLineSize;
|
||||
|
||||
static const size_t maskSizeClassMax = 512;
|
||||
static const size_t smallMax = 32 * kB;
|
||||
|
||||
static const size_t pageSizeMax = smallMax * 2;
|
||||
static const size_t pageClassCount = pageSizeMax / smallPageSize;
|
||||
|
||||
static const size_t pageSizeWasteFactor = 8;
|
||||
static const size_t logWasteFactor = 8;
|
||||
|
||||
static const size_t largeAlignment = smallMax / pageSizeWasteFactor;
|
||||
static const size_t largeAlignmentMask = largeAlignment - 1;
|
||||
|
||||
static const size_t deallocatorLogCapacity = 256;
|
||||
static const size_t bumpRangeCacheCapacity = 3;
|
||||
|
||||
static const std::chrono::milliseconds scavengeSleepDuration = std::chrono::milliseconds(512);
|
||||
|
||||
static const size_t maskSizeClassCount = maskSizeClassMax / alignment;
|
||||
|
||||
inline constexpr size_t maskSizeClass(size_t size)
|
||||
{
|
||||
// We mask to accommodate zero.
|
||||
return mask((size - 1) / alignment, maskSizeClassCount - 1);
|
||||
}
|
||||
|
||||
inline size_t maskObjectSize(size_t maskSizeClass)
|
||||
{
|
||||
return (maskSizeClass + 1) * alignment;
|
||||
}
|
||||
|
||||
static const size_t logAlignmentMin = maskSizeClassMax / logWasteFactor;
|
||||
|
||||
static const size_t logSizeClassCount = (log2(smallMax) - log2(maskSizeClassMax)) * logWasteFactor;
|
||||
|
||||
inline size_t logSizeClass(size_t size)
|
||||
{
|
||||
size_t base = log2(size - 1) - log2(maskSizeClassMax);
|
||||
size_t offset = (size - 1 - (maskSizeClassMax << base));
|
||||
return base * logWasteFactor + offset / (logAlignmentMin << base);
|
||||
}
|
||||
|
||||
inline size_t logObjectSize(size_t logSizeClass)
|
||||
{
|
||||
size_t base = logSizeClass / logWasteFactor;
|
||||
size_t offset = logSizeClass % logWasteFactor;
|
||||
return (maskSizeClassMax << base) + (offset + 1) * (logAlignmentMin << base);
|
||||
}
|
||||
|
||||
static const size_t sizeClassCount = maskSizeClassCount + logSizeClassCount;
|
||||
|
||||
inline size_t sizeClass(size_t size)
|
||||
{
|
||||
if (size <= maskSizeClassMax)
|
||||
return maskSizeClass(size);
|
||||
return maskSizeClassCount + logSizeClass(size);
|
||||
}
|
||||
|
||||
inline size_t objectSize(size_t sizeClass)
|
||||
{
|
||||
if (sizeClass < maskSizeClassCount)
|
||||
return maskObjectSize(sizeClass);
|
||||
return logObjectSize(sizeClass - maskSizeClassCount);
|
||||
}
|
||||
|
||||
inline size_t pageSize(size_t pageClass)
|
||||
{
|
||||
return (pageClass + 1) * smallPageSize;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Sizes;
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Sizes_h
|
69
bmalloc/SmallLine.h
Normal file
69
bmalloc/SmallLine.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SmallLine_h
|
||||
#define SmallLine_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "Mutex.h"
|
||||
#include "ObjectType.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class SmallLine {
|
||||
public:
|
||||
void ref(std::lock_guard<StaticMutex>&, unsigned char = 1);
|
||||
bool deref(std::lock_guard<StaticMutex>&);
|
||||
unsigned refCount(std::lock_guard<StaticMutex>&) { return m_refCount; }
|
||||
|
||||
char* begin();
|
||||
char* end();
|
||||
|
||||
private:
|
||||
unsigned char m_refCount;
|
||||
|
||||
static_assert(
|
||||
smallLineSize / alignment <= std::numeric_limits<decltype(m_refCount)>::max(),
|
||||
"maximum object count must fit in SmallLine::m_refCount");
|
||||
|
||||
};
|
||||
|
||||
inline void SmallLine::ref(std::lock_guard<StaticMutex>&, unsigned char refCount)
|
||||
{
|
||||
BASSERT(!m_refCount);
|
||||
m_refCount = refCount;
|
||||
}
|
||||
|
||||
inline bool SmallLine::deref(std::lock_guard<StaticMutex>&)
|
||||
{
|
||||
BASSERT(m_refCount);
|
||||
--m_refCount;
|
||||
return !m_refCount;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // SmallLine_h
|
87
bmalloc/SmallPage.h
Normal file
87
bmalloc/SmallPage.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SmallPage_h
|
||||
#define SmallPage_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "List.h"
|
||||
#include "Mutex.h"
|
||||
#include "VMAllocate.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class SmallPage : public ListNode<SmallPage> {
|
||||
public:
|
||||
SmallPage()
|
||||
: m_hasFreeLines(true)
|
||||
{
|
||||
}
|
||||
|
||||
void ref(std::lock_guard<StaticMutex>&);
|
||||
bool deref(std::lock_guard<StaticMutex>&);
|
||||
unsigned refCount(std::lock_guard<StaticMutex>&) { return m_refCount; }
|
||||
|
||||
size_t sizeClass() { return m_sizeClass; }
|
||||
void setSizeClass(size_t sizeClass) { m_sizeClass = sizeClass; }
|
||||
|
||||
bool hasFreeLines(std::lock_guard<StaticMutex>&) const { return m_hasFreeLines; }
|
||||
void setHasFreeLines(std::lock_guard<StaticMutex>&, bool hasFreeLines) { m_hasFreeLines = hasFreeLines; }
|
||||
|
||||
SmallLine* begin();
|
||||
|
||||
unsigned char slide() const { return m_slide; }
|
||||
void setSlide(unsigned char slide) { m_slide = slide; }
|
||||
|
||||
private:
|
||||
unsigned char m_hasFreeLines: 1;
|
||||
unsigned char m_refCount: 7;
|
||||
unsigned char m_sizeClass;
|
||||
unsigned char m_slide;
|
||||
|
||||
static_assert(
|
||||
sizeClassCount <= std::numeric_limits<decltype(m_sizeClass)>::max(),
|
||||
"Largest size class must fit in SmallPage metadata");
|
||||
};
|
||||
|
||||
inline void SmallPage::ref(std::lock_guard<StaticMutex>&)
|
||||
{
|
||||
BASSERT(!m_slide);
|
||||
++m_refCount;
|
||||
BASSERT(m_refCount);
|
||||
}
|
||||
|
||||
inline bool SmallPage::deref(std::lock_guard<StaticMutex>&)
|
||||
{
|
||||
BASSERT(!m_slide);
|
||||
BASSERT(m_refCount);
|
||||
--m_refCount;
|
||||
return !m_refCount;
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // SmallPage_h
|
53
bmalloc/StaticMutex.cpp
Normal file
53
bmalloc/StaticMutex.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ScopeExit.h"
|
||||
#include "StaticMutex.h"
|
||||
#include <thread>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
void StaticMutex::lockSlowCase()
|
||||
{
|
||||
// The longest critical section in bmalloc is much shorter than the
|
||||
// time it takes to make a system call to yield to the OS scheduler.
|
||||
// So, we try again a lot before we yield.
|
||||
static const size_t aLot = 256;
|
||||
|
||||
if (!m_isSpinning.test_and_set()) {
|
||||
auto clear = makeScopeExit([&] { m_isSpinning.clear(); });
|
||||
|
||||
for (size_t i = 0; i < aLot; ++i) {
|
||||
if (try_lock())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid spinning pathologically.
|
||||
while (!try_lock())
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
103
bmalloc/StaticMutex.h
Normal file
103
bmalloc/StaticMutex.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef StaticMutex_h
|
||||
#define StaticMutex_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
// A fast replacement for std::mutex, for use in static storage.
|
||||
|
||||
// Use StaticMutex in static storage, where global constructors and exit-time
|
||||
// destructors are prohibited, but all memory is zero-initialized automatically.
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class StaticMutex {
|
||||
protected:
|
||||
// Subclasses that support non-static storage must use explicit initialization.
|
||||
void init();
|
||||
|
||||
public:
|
||||
void lock();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
void lockSlowCase();
|
||||
|
||||
std::atomic_flag m_flag;
|
||||
std::atomic_flag m_isSpinning;
|
||||
};
|
||||
|
||||
static inline void sleep(
|
||||
std::unique_lock<StaticMutex>& lock, std::chrono::milliseconds duration)
|
||||
{
|
||||
if (duration == std::chrono::milliseconds(0))
|
||||
return;
|
||||
|
||||
lock.unlock();
|
||||
std::this_thread::sleep_for(duration);
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
static inline void waitUntilFalse(
|
||||
std::unique_lock<StaticMutex>& lock, std::chrono::milliseconds sleepDuration,
|
||||
bool& condition)
|
||||
{
|
||||
while (condition) {
|
||||
condition = false;
|
||||
sleep(lock, sleepDuration);
|
||||
}
|
||||
}
|
||||
|
||||
inline void StaticMutex::init()
|
||||
{
|
||||
m_flag.clear();
|
||||
m_isSpinning.clear();
|
||||
}
|
||||
|
||||
inline bool StaticMutex::try_lock()
|
||||
{
|
||||
return !m_flag.test_and_set(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
inline void StaticMutex::lock()
|
||||
{
|
||||
if (!try_lock())
|
||||
lockSlowCase();
|
||||
}
|
||||
|
||||
inline void StaticMutex::unlock()
|
||||
{
|
||||
m_flag.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // StaticMutex_h
|
35
bmalloc/Syscall.h
Normal file
35
bmalloc/Syscall.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Syscall_h
|
||||
#define Syscall_h
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define SYSCALL(x) do { \
|
||||
while ((x) == -1 && errno == EAGAIN) { } \
|
||||
} while (0);
|
||||
|
||||
#endif // Syscall_h
|
230
bmalloc/VMAllocate.h
Normal file
230
bmalloc/VMAllocate.h
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VMAllocate_h
|
||||
#define VMAllocate_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include "Logging.h"
|
||||
#include "Range.h"
|
||||
#include "Sizes.h"
|
||||
#include "Syscall.h"
|
||||
#include <algorithm>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if BOS(DARWIN)
|
||||
#include <mach/vm_page_size.h>
|
||||
#include <mach/vm_statistics.h>
|
||||
#endif
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
#if BOS(DARWIN)
|
||||
#define BMALLOC_VM_TAG VM_MAKE_TAG(VM_MEMORY_TCMALLOC)
|
||||
#else
|
||||
#define BMALLOC_VM_TAG -1
|
||||
#endif
|
||||
|
||||
inline size_t vmPageSize()
|
||||
{
|
||||
static size_t cached;
|
||||
if (!cached)
|
||||
cached = sysconf(_SC_PAGESIZE);
|
||||
return cached;
|
||||
}
|
||||
|
||||
inline size_t vmPageShift()
|
||||
{
|
||||
static size_t cached;
|
||||
if (!cached)
|
||||
cached = log2(vmPageSize());
|
||||
return cached;
|
||||
}
|
||||
|
||||
inline size_t vmSize(size_t size)
|
||||
{
|
||||
return roundUpToMultipleOf(vmPageSize(), size);
|
||||
}
|
||||
|
||||
inline void vmValidate(size_t vmSize)
|
||||
{
|
||||
UNUSED(vmSize);
|
||||
BASSERT(vmSize);
|
||||
BASSERT(vmSize == roundUpToMultipleOf(vmPageSize(), vmSize));
|
||||
}
|
||||
|
||||
inline void vmValidate(void* p, size_t vmSize)
|
||||
{
|
||||
vmValidate(vmSize);
|
||||
|
||||
UNUSED(p);
|
||||
BASSERT(p);
|
||||
BASSERT(p == mask(p, ~(vmPageSize() - 1)));
|
||||
}
|
||||
|
||||
inline size_t vmPageSizePhysical()
|
||||
{
|
||||
#if (BPLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
|
||||
return vm_kernel_page_size;
|
||||
#else
|
||||
static size_t cached;
|
||||
if (!cached)
|
||||
cached = sysconf(_SC_PAGESIZE);
|
||||
return cached;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void vmValidatePhysical(size_t vmSize)
|
||||
{
|
||||
UNUSED(vmSize);
|
||||
BASSERT(vmSize);
|
||||
BASSERT(vmSize == roundUpToMultipleOf(vmPageSizePhysical(), vmSize));
|
||||
}
|
||||
|
||||
inline void vmValidatePhysical(void* p, size_t vmSize)
|
||||
{
|
||||
vmValidatePhysical(vmSize);
|
||||
|
||||
UNUSED(p);
|
||||
BASSERT(p);
|
||||
BASSERT(p == mask(p, ~(vmPageSizePhysical() - 1)));
|
||||
}
|
||||
|
||||
inline void* tryVMAllocate(size_t vmSize)
|
||||
{
|
||||
vmValidate(vmSize);
|
||||
void* result = mmap(0, vmSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, BMALLOC_VM_TAG, 0);
|
||||
if (result == MAP_FAILED) {
|
||||
logVMFailure();
|
||||
return nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void* vmAllocate(size_t vmSize)
|
||||
{
|
||||
void* result = tryVMAllocate(vmSize);
|
||||
RELEASE_BASSERT(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void vmDeallocate(void* p, size_t vmSize)
|
||||
{
|
||||
vmValidate(p, vmSize);
|
||||
munmap(p, vmSize);
|
||||
}
|
||||
|
||||
inline void vmRevokePermissions(void* p, size_t vmSize)
|
||||
{
|
||||
vmValidate(p, vmSize);
|
||||
mprotect(p, vmSize, PROT_NONE);
|
||||
}
|
||||
|
||||
// Allocates vmSize bytes at a specified power-of-two alignment.
|
||||
// Use this function to create maskable memory regions.
|
||||
|
||||
inline void* tryVMAllocate(size_t vmAlignment, size_t vmSize)
|
||||
{
|
||||
vmValidate(vmSize);
|
||||
vmValidate(vmAlignment);
|
||||
|
||||
size_t mappedSize = vmAlignment + vmSize;
|
||||
if (mappedSize < vmAlignment || mappedSize < vmSize) // Check for overflow
|
||||
return nullptr;
|
||||
|
||||
char* mapped = static_cast<char*>(tryVMAllocate(mappedSize));
|
||||
if (!mapped)
|
||||
return nullptr;
|
||||
char* mappedEnd = mapped + mappedSize;
|
||||
|
||||
char* aligned = roundUpToMultipleOf(vmAlignment, mapped);
|
||||
char* alignedEnd = aligned + vmSize;
|
||||
|
||||
RELEASE_BASSERT(alignedEnd <= mappedEnd);
|
||||
|
||||
if (size_t leftExtra = aligned - mapped)
|
||||
vmDeallocate(mapped, leftExtra);
|
||||
|
||||
if (size_t rightExtra = mappedEnd - alignedEnd)
|
||||
vmDeallocate(alignedEnd, rightExtra);
|
||||
|
||||
return aligned;
|
||||
}
|
||||
|
||||
inline void* vmAllocate(size_t vmAlignment, size_t vmSize)
|
||||
{
|
||||
void* result = tryVMAllocate(vmAlignment, vmSize);
|
||||
RELEASE_BASSERT(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void vmDeallocatePhysicalPages(void* p, size_t vmSize)
|
||||
{
|
||||
vmValidatePhysical(p, vmSize);
|
||||
#if BOS(DARWIN)
|
||||
SYSCALL(madvise(p, vmSize, MADV_FREE_REUSABLE));
|
||||
#else
|
||||
SYSCALL(madvise(p, vmSize, MADV_DONTNEED));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void vmAllocatePhysicalPages(void* p, size_t vmSize)
|
||||
{
|
||||
vmValidatePhysical(p, vmSize);
|
||||
#if BOS(DARWIN)
|
||||
SYSCALL(madvise(p, vmSize, MADV_FREE_REUSE));
|
||||
#else
|
||||
SYSCALL(madvise(p, vmSize, MADV_NORMAL));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Trims requests that are un-page-aligned.
|
||||
inline void vmDeallocatePhysicalPagesSloppy(void* p, size_t size)
|
||||
{
|
||||
char* begin = roundUpToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p));
|
||||
char* end = roundDownToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p) + size);
|
||||
|
||||
if (begin >= end)
|
||||
return;
|
||||
|
||||
vmDeallocatePhysicalPages(begin, end - begin);
|
||||
}
|
||||
|
||||
// Expands requests that are un-page-aligned.
|
||||
inline void vmAllocatePhysicalPagesSloppy(void* p, size_t size)
|
||||
{
|
||||
char* begin = roundDownToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p));
|
||||
char* end = roundUpToMultipleOf(vmPageSizePhysical(), static_cast<char*>(p) + size);
|
||||
|
||||
if (begin >= end)
|
||||
return;
|
||||
|
||||
vmAllocatePhysicalPages(begin, end - begin);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // VMAllocate_h
|
101
bmalloc/VMHeap.cpp
Normal file
101
bmalloc/VMHeap.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "PerProcess.h"
|
||||
#include "VMHeap.h"
|
||||
#include <thread>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
LargeRange VMHeap::tryAllocateLargeChunk(std::lock_guard<StaticMutex>&, size_t alignment, size_t size)
|
||||
{
|
||||
// We allocate VM in aligned multiples to increase the chances that
|
||||
// the OS will provide contiguous ranges that we can merge.
|
||||
size_t roundedAlignment = roundUpToMultipleOf<chunkSize>(alignment);
|
||||
if (roundedAlignment < alignment) // Check for overflow
|
||||
return LargeRange();
|
||||
alignment = roundedAlignment;
|
||||
|
||||
size_t roundedSize = roundUpToMultipleOf<chunkSize>(size);
|
||||
if (roundedSize < size) // Check for overflow
|
||||
return LargeRange();
|
||||
size = roundedSize;
|
||||
|
||||
void* memory = tryVMAllocate(alignment, size);
|
||||
if (!memory)
|
||||
return LargeRange();
|
||||
|
||||
Chunk* chunk = static_cast<Chunk*>(memory);
|
||||
|
||||
#if BOS(DARWIN)
|
||||
m_zone.addRange(Range(chunk->bytes(), size));
|
||||
#endif
|
||||
|
||||
return LargeRange(chunk->bytes(), size, 0);
|
||||
}
|
||||
|
||||
void VMHeap::allocateSmallChunk(std::lock_guard<StaticMutex>& lock, size_t pageClass)
|
||||
{
|
||||
size_t pageSize = bmalloc::pageSize(pageClass);
|
||||
size_t smallPageCount = pageSize / smallPageSize;
|
||||
|
||||
void* memory = vmAllocate(chunkSize, chunkSize);
|
||||
Chunk* chunk = static_cast<Chunk*>(memory);
|
||||
|
||||
// We align to our page size in order to honor OS APIs and in order to
|
||||
// guarantee that we can service aligned allocation requests at equal
|
||||
// and smaller powers of two.
|
||||
size_t vmPageSize = roundUpToMultipleOf(bmalloc::vmPageSize(), pageSize);
|
||||
size_t metadataSize = roundUpToMultipleOfNonPowerOfTwo(vmPageSize, sizeof(Chunk));
|
||||
|
||||
Object begin(chunk, metadataSize);
|
||||
Object end(chunk, chunkSize);
|
||||
|
||||
// Establish guard pages before writing to Chunk memory to work around
|
||||
// an edge case in the Darwin VM system (<rdar://problem/25910098>).
|
||||
vmRevokePermissions(begin.address(), vmPageSize);
|
||||
vmRevokePermissions(end.address() - vmPageSize, vmPageSize);
|
||||
|
||||
begin = begin + vmPageSize;
|
||||
end = end - vmPageSize;
|
||||
BASSERT(begin <= end && end.offset() - begin.offset() >= pageSize);
|
||||
|
||||
new (chunk) Chunk(lock);
|
||||
|
||||
#if BOS(DARWIN)
|
||||
m_zone.addRange(Range(begin.address(), end.address() - begin.address()));
|
||||
#endif
|
||||
|
||||
for (Object it = begin; it + pageSize <= end; it = it + pageSize) {
|
||||
SmallPage* page = it.page();
|
||||
|
||||
for (size_t i = 0; i < smallPageCount; ++i)
|
||||
page[i].setSlide(i);
|
||||
|
||||
m_smallPages[pageClass].push(page);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
82
bmalloc/VMHeap.h
Normal file
82
bmalloc/VMHeap.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef VMHeap_h
|
||||
#define VMHeap_h
|
||||
|
||||
#include "Chunk.h"
|
||||
#include "FixedVector.h"
|
||||
#include "LargeRange.h"
|
||||
#include "Map.h"
|
||||
#include "Vector.h"
|
||||
#if BOS(DARWIN)
|
||||
#include "Zone.h"
|
||||
#endif
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class BeginTag;
|
||||
class EndTag;
|
||||
class Heap;
|
||||
|
||||
class VMHeap {
|
||||
public:
|
||||
SmallPage* allocateSmallPage(std::lock_guard<StaticMutex>&, size_t);
|
||||
void deallocateSmallPage(std::unique_lock<StaticMutex>&, size_t, SmallPage*);
|
||||
|
||||
LargeRange tryAllocateLargeChunk(std::lock_guard<StaticMutex>&, size_t alignment, size_t);
|
||||
|
||||
private:
|
||||
void allocateSmallChunk(std::lock_guard<StaticMutex>&, size_t);
|
||||
|
||||
std::array<List<SmallPage>, pageClassCount> m_smallPages;
|
||||
|
||||
#if BOS(DARWIN)
|
||||
Zone m_zone;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline SmallPage* VMHeap::allocateSmallPage(std::lock_guard<StaticMutex>& lock, size_t pageClass)
|
||||
{
|
||||
if (m_smallPages[pageClass].isEmpty())
|
||||
allocateSmallChunk(lock, pageClass);
|
||||
|
||||
SmallPage* page = m_smallPages[pageClass].pop();
|
||||
vmAllocatePhysicalPagesSloppy(page->begin()->begin(), pageSize(pageClass));
|
||||
return page;
|
||||
}
|
||||
|
||||
inline void VMHeap::deallocateSmallPage(std::unique_lock<StaticMutex>& lock, size_t pageClass, SmallPage* page)
|
||||
{
|
||||
lock.unlock();
|
||||
vmDeallocatePhysicalPagesSloppy(page->begin()->begin(), pageSize(pageClass));
|
||||
lock.lock();
|
||||
|
||||
m_smallPages[pageClass].push(page);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // VMHeap_h
|
237
bmalloc/Vector.h
Normal file
237
bmalloc/Vector.h
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Vector_h
|
||||
#define Vector_h
|
||||
|
||||
#include "Inline.h"
|
||||
#include "VMAllocate.h"
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
// A replacement for std::vector that allocates using vmAllocate instead of
|
||||
// malloc, shrinks automatically, and supports "popping" from the middle.
|
||||
|
||||
template<typename T>
|
||||
class Vector {
|
||||
static_assert(std::is_trivially_destructible<T>::value, "Vector must have a trivial destructor.");
|
||||
public:
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
|
||||
Vector();
|
||||
Vector(Vector&&);
|
||||
~Vector();
|
||||
|
||||
iterator begin() { return m_buffer; }
|
||||
iterator end() { return m_buffer + m_size; }
|
||||
|
||||
size_t size() { return m_size; }
|
||||
size_t capacity() { return m_capacity; }
|
||||
|
||||
T& operator[](size_t);
|
||||
T& last() { return m_buffer[m_size - 1]; }
|
||||
|
||||
void push(const T&);
|
||||
|
||||
T pop();
|
||||
T pop(size_t);
|
||||
T pop(const_iterator it) { return pop(it - begin()); }
|
||||
|
||||
void insert(iterator, const T&);
|
||||
T remove(iterator);
|
||||
|
||||
void grow(size_t);
|
||||
void shrink(size_t);
|
||||
void resize(size_t);
|
||||
|
||||
void shrinkToFit();
|
||||
|
||||
private:
|
||||
static const size_t growFactor = 2;
|
||||
static const size_t shrinkFactor = 4;
|
||||
static size_t initialCapacity() { return vmPageSize() / sizeof(T); }
|
||||
|
||||
void growCapacity();
|
||||
void shrinkCapacity();
|
||||
void reallocateBuffer(size_t);
|
||||
|
||||
T* m_buffer;
|
||||
size_t m_size;
|
||||
size_t m_capacity;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline Vector<T>::Vector()
|
||||
: m_buffer(nullptr)
|
||||
, m_size(0)
|
||||
, m_capacity(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Vector<T>::Vector(Vector&& other)
|
||||
: m_buffer(other.m_buffer)
|
||||
, m_size(other.m_size)
|
||||
, m_capacity(other.m_capacity)
|
||||
{
|
||||
other.m_buffer = nullptr;
|
||||
other.m_size = 0;
|
||||
other.m_capacity = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vector<T>::~Vector()
|
||||
{
|
||||
if (m_buffer)
|
||||
vmDeallocate(m_buffer, vmSize(m_capacity * sizeof(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T& Vector<T>::operator[](size_t i)
|
||||
{
|
||||
BASSERT(i < m_size);
|
||||
return m_buffer[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
INLINE void Vector<T>::push(const T& value)
|
||||
{
|
||||
if (m_size == m_capacity)
|
||||
growCapacity();
|
||||
m_buffer[m_size++] = value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T Vector<T>::pop()
|
||||
{
|
||||
BASSERT(m_size);
|
||||
T value = m_buffer[m_size - 1];
|
||||
shrink(m_size - 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T Vector<T>::pop(size_t i)
|
||||
{
|
||||
BASSERT(i < m_size);
|
||||
std::swap(m_buffer[i], last());
|
||||
return pop();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Vector<T>::insert(iterator it, const T& value)
|
||||
{
|
||||
size_t index = it - begin();
|
||||
size_t moveCount = end() - it;
|
||||
|
||||
grow(m_size + 1);
|
||||
std::memmove(&m_buffer[index + 1], &m_buffer[index], moveCount * sizeof(T));
|
||||
|
||||
m_buffer[index] = value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Vector<T>::remove(iterator it)
|
||||
{
|
||||
size_t index = it - begin();
|
||||
size_t moveCount = end() - it - 1;
|
||||
|
||||
T result = *it;
|
||||
|
||||
std::memmove(&m_buffer[index], &m_buffer[index + 1], moveCount * sizeof(T));
|
||||
shrink(m_size - 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void Vector<T>::grow(size_t size)
|
||||
{
|
||||
BASSERT(size >= m_size);
|
||||
while (m_size < size)
|
||||
push(T());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void Vector<T>::shrink(size_t size)
|
||||
{
|
||||
BASSERT(size <= m_size);
|
||||
m_size = size;
|
||||
if (m_size < m_capacity / shrinkFactor && m_capacity > initialCapacity())
|
||||
shrinkCapacity();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void Vector<T>::resize(size_t size)
|
||||
{
|
||||
if (size <= m_size)
|
||||
shrink(size);
|
||||
else
|
||||
grow(size);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Vector<T>::reallocateBuffer(size_t newCapacity)
|
||||
{
|
||||
RELEASE_BASSERT(newCapacity < std::numeric_limits<size_t>::max() / sizeof(T));
|
||||
|
||||
size_t vmSize = bmalloc::vmSize(newCapacity * sizeof(T));
|
||||
T* newBuffer = vmSize ? static_cast<T*>(vmAllocate(vmSize)) : nullptr;
|
||||
if (m_buffer) {
|
||||
std::memcpy(newBuffer, m_buffer, m_size * sizeof(T));
|
||||
vmDeallocate(m_buffer, bmalloc::vmSize(m_capacity * sizeof(T)));
|
||||
}
|
||||
|
||||
m_buffer = newBuffer;
|
||||
m_capacity = vmSize / sizeof(T);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NO_INLINE void Vector<T>::shrinkCapacity()
|
||||
{
|
||||
size_t newCapacity = max(initialCapacity(), m_capacity / shrinkFactor);
|
||||
reallocateBuffer(newCapacity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NO_INLINE void Vector<T>::growCapacity()
|
||||
{
|
||||
size_t newCapacity = max(initialCapacity(), m_size * growFactor);
|
||||
reallocateBuffer(newCapacity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Vector<T>::shrinkToFit()
|
||||
{
|
||||
if (m_size < m_capacity)
|
||||
reallocateBuffer(m_size);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Vector_h
|
132
bmalloc/Zone.cpp
Normal file
132
bmalloc/Zone.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Sizes.h"
|
||||
#include "Zone.h"
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
template<typename T> static void remoteRead(task_t task, memory_reader_t reader, vm_address_t remotePointer, T& result)
|
||||
{
|
||||
void* tmp = nullptr;
|
||||
kern_return_t error = reader(task, remotePointer, sizeof(T), &tmp);
|
||||
|
||||
// This read sometimes fails for unknown reasons (<rdar://problem/14093757>).
|
||||
// Avoid a crash by skipping the memcpy when this happens.
|
||||
if (error || !tmp) {
|
||||
fprintf(stderr, "bmalloc: error reading remote process: 0x%x\n", error);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&result, tmp, sizeof(T));
|
||||
}
|
||||
|
||||
// These function pointers are invoked unconditionally on all zones by various
|
||||
// system tools. We don't support any of these features, but we provide
|
||||
// just enough functionality not to crash.
|
||||
|
||||
static size_t good_size(malloc_zone_t*, size_t size)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
static boolean_t check(malloc_zone_t*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void print(malloc_zone_t*, boolean_t)
|
||||
{
|
||||
}
|
||||
|
||||
static void log(malloc_zone_t*, void*)
|
||||
{
|
||||
}
|
||||
|
||||
static void force_lock(malloc_zone_t*)
|
||||
{
|
||||
}
|
||||
|
||||
static void force_unlock(malloc_zone_t*)
|
||||
{
|
||||
}
|
||||
|
||||
static void statistics(malloc_zone_t*, malloc_statistics_t* statistics)
|
||||
{
|
||||
memset(statistics, 0, sizeof(malloc_statistics_t));
|
||||
}
|
||||
|
||||
static size_t zoneSize(malloc_zone_t*, const void*)
|
||||
{
|
||||
// Our zone is not public API, so no pointer can belong to us.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This function runs inside the leaks process.
|
||||
static kern_return_t enumerator(task_t task, void* context, unsigned type_mask, vm_address_t zone_address, memory_reader_t reader, vm_range_recorder_t recorder)
|
||||
{
|
||||
Zone remoteZone(task, reader, zone_address);
|
||||
for (auto& range : remoteZone.ranges()) {
|
||||
vm_range_t vmRange = { reinterpret_cast<vm_address_t>(range.begin()), range.size() };
|
||||
|
||||
if ((type_mask & MALLOC_PTR_REGION_RANGE_TYPE))
|
||||
(*recorder)(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &vmRange, 1);
|
||||
|
||||
if ((type_mask & MALLOC_PTR_IN_USE_RANGE_TYPE))
|
||||
(*recorder)(task, context, MALLOC_PTR_IN_USE_RANGE_TYPE, &vmRange, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The memory analysis API requires the contents of this struct to be a static
|
||||
// constant in the program binary. The leaks process will load this struct
|
||||
// out of the program binary (and not out of the running process).
|
||||
static const malloc_introspection_t zoneIntrospect = {
|
||||
.enumerator = bmalloc::enumerator,
|
||||
.good_size = bmalloc::good_size,
|
||||
.check = bmalloc::check,
|
||||
.print = bmalloc::print,
|
||||
.log = bmalloc::log,
|
||||
.force_lock = bmalloc::force_lock,
|
||||
.force_unlock = bmalloc::force_unlock,
|
||||
.statistics = bmalloc::statistics
|
||||
};
|
||||
|
||||
Zone::Zone()
|
||||
{
|
||||
malloc_zone_t::size = &bmalloc::zoneSize;
|
||||
malloc_zone_t::zone_name = "WebKit Malloc";
|
||||
malloc_zone_t::introspect = const_cast<malloc_introspection_t*>(&bmalloc::zoneIntrospect);
|
||||
malloc_zone_t::version = 4;
|
||||
malloc_zone_register(this);
|
||||
}
|
||||
|
||||
Zone::Zone(task_t task, memory_reader_t reader, vm_address_t remotePointer)
|
||||
{
|
||||
remoteRead(task, reader, remotePointer, *this);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
73
bmalloc/Zone.h
Normal file
73
bmalloc/Zone.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef Zone_h
|
||||
#define Zone_h
|
||||
|
||||
#include "FixedVector.h"
|
||||
#include "Range.h"
|
||||
#include <malloc/malloc.h>
|
||||
|
||||
namespace bmalloc {
|
||||
|
||||
class Chunk;
|
||||
|
||||
class Zone : public malloc_zone_t {
|
||||
public:
|
||||
// Enough capacity to track a 64GB heap, so probably enough for anything.
|
||||
static const size_t capacity = 2048;
|
||||
|
||||
Zone();
|
||||
Zone(task_t, memory_reader_t, vm_address_t);
|
||||
|
||||
void addRange(Range);
|
||||
FixedVector<Range, capacity>& ranges() { return m_ranges; }
|
||||
|
||||
private:
|
||||
// This vector has two purposes:
|
||||
// (1) It stores the list of Chunks so that we can enumerate
|
||||
// each Chunk and request that it be scanned if reachable.
|
||||
// (2) It roots a pointer to each Chunk in a global non-malloc
|
||||
// VM region, making each Chunk appear reachable, and therefore
|
||||
// ensuring that the leaks tool will scan it. (The leaks tool
|
||||
// conservatively scans all writeable VM regions that are not malloc
|
||||
// regions, and then scans malloc regions using the introspection API.)
|
||||
// This prevents the leaks tool from reporting false positive leaks for
|
||||
// objects pointed to from bmalloc memory -- though it also prevents the
|
||||
// leaks tool from finding any leaks in bmalloc memory.
|
||||
FixedVector<Range, capacity> m_ranges;
|
||||
};
|
||||
|
||||
inline void Zone::addRange(Range range)
|
||||
{
|
||||
if (m_ranges.size() == m_ranges.capacity())
|
||||
return;
|
||||
|
||||
m_ranges.push(range);
|
||||
}
|
||||
|
||||
} // namespace bmalloc
|
||||
|
||||
#endif // Zone_h
|
97
bmalloc/bmalloc.h
Normal file
97
bmalloc/bmalloc.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Heap.h"
|
||||
#include "PerProcess.h"
|
||||
#include "StaticMutex.h"
|
||||
|
||||
namespace bmalloc {
|
||||
namespace api {
|
||||
|
||||
// Returns null on failure.
|
||||
inline void* tryMalloc(size_t size)
|
||||
{
|
||||
return Cache::tryAllocate(size);
|
||||
}
|
||||
|
||||
// Crashes on failure.
|
||||
inline void* malloc(size_t size)
|
||||
{
|
||||
return Cache::allocate(size);
|
||||
}
|
||||
|
||||
// Returns null on failure.
|
||||
inline void* tryMemalign(size_t alignment, size_t size)
|
||||
{
|
||||
return Cache::tryAllocate(alignment, size);
|
||||
}
|
||||
|
||||
// Crashes on failure.
|
||||
inline void* memalign(size_t alignment, size_t size)
|
||||
{
|
||||
return Cache::allocate(alignment, size);
|
||||
}
|
||||
|
||||
// Crashes on failure.
|
||||
inline void* realloc(void* object, size_t newSize)
|
||||
{
|
||||
return Cache::reallocate(object, newSize);
|
||||
}
|
||||
|
||||
inline void free(void* object)
|
||||
{
|
||||
Cache::deallocate(object);
|
||||
}
|
||||
|
||||
inline void scavengeThisThread()
|
||||
{
|
||||
Cache::scavenge();
|
||||
}
|
||||
|
||||
inline void scavenge()
|
||||
{
|
||||
scavengeThisThread();
|
||||
|
||||
std::unique_lock<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
PerProcess<Heap>::get()->scavenge(lock, std::chrono::milliseconds(0));
|
||||
}
|
||||
|
||||
inline bool isEnabled()
|
||||
{
|
||||
std::unique_lock<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
return PerProcess<Heap>::getFastCase()->environment().isBmallocEnabled();
|
||||
}
|
||||
|
||||
#if BOS(DARWIN)
|
||||
inline void setScavengerThreadQOSClass(qos_class_t overrideClass)
|
||||
{
|
||||
std::unique_lock<StaticMutex> lock(PerProcess<Heap>::mutex());
|
||||
PerProcess<Heap>::getFastCase()->setScavengerThreadQOSClass(overrideClass);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace api
|
||||
} // namespace bmalloc
|
66
bmalloc/darwin/BSoftLinking.h
Normal file
66
bmalloc/darwin/BSoftLinking.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2007, 2008, 2011-2016 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BSoftLinking_h
|
||||
#define BSoftLinking_h
|
||||
|
||||
#include "BAssert.h"
|
||||
#include <dlfcn.h>
|
||||
#include <mutex>
|
||||
|
||||
#define BSOFT_LINK_PRIVATE_FRAMEWORK(framework) \
|
||||
static void* framework##Library() \
|
||||
{ \
|
||||
static void* frameworkLibrary; \
|
||||
static std::once_flag once; \
|
||||
std::call_once(once, [] { \
|
||||
frameworkLibrary = dlopen("/System/Library/PrivateFrameworks/" #framework ".framework/" #framework, RTLD_NOW); \
|
||||
RELEASE_BASSERT_WITH_MESSAGE(frameworkLibrary, "%s", dlerror()); \
|
||||
}); \
|
||||
return frameworkLibrary; \
|
||||
}
|
||||
|
||||
#define BSOFT_LINK_FUNCTION(framework, functionName, resultType, parameterDeclarations, parameterNames) \
|
||||
extern "C" { \
|
||||
resultType functionName parameterDeclarations; \
|
||||
} \
|
||||
static resultType init##functionName parameterDeclarations; \
|
||||
static resultType (*softLink##functionName) parameterDeclarations = init##functionName; \
|
||||
\
|
||||
static resultType init##functionName parameterDeclarations \
|
||||
{ \
|
||||
static std::once_flag once; \
|
||||
std::call_once(once, [] { \
|
||||
softLink##functionName = (resultType (*) parameterDeclarations) dlsym(framework##Library(), #functionName); \
|
||||
RELEASE_BASSERT_WITH_MESSAGE(softLink##functionName, "%s", dlerror()); \
|
||||
}); \
|
||||
return softLink##functionName parameterNames; \
|
||||
} \
|
||||
\
|
||||
inline resultType functionName parameterDeclarations \
|
||||
{ \
|
||||
return softLink##functionName parameterNames; \
|
||||
}
|
||||
|
||||
#endif // BSoftLinking_h
|
63
bmalloc/mbmalloc.cpp
Normal file
63
bmalloc/mbmalloc.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "bmalloc.h"
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
extern "C" {
|
||||
|
||||
EXPORT void* mbmalloc(size_t);
|
||||
EXPORT void* mbmemalign(size_t, size_t);
|
||||
EXPORT void mbfree(void*, size_t);
|
||||
EXPORT void* mbrealloc(void*, size_t, size_t);
|
||||
EXPORT void mbscavenge();
|
||||
|
||||
void* mbmalloc(size_t size)
|
||||
{
|
||||
return bmalloc::api::malloc(size);
|
||||
}
|
||||
|
||||
void* mbmemalign(size_t alignment, size_t size)
|
||||
{
|
||||
return bmalloc::api::memalign(alignment, size);
|
||||
}
|
||||
|
||||
void mbfree(void* p, size_t)
|
||||
{
|
||||
bmalloc::api::free(p);
|
||||
}
|
||||
|
||||
void* mbrealloc(void* p, size_t, size_t size)
|
||||
{
|
||||
return bmalloc::api::realloc(p, size);
|
||||
}
|
||||
|
||||
void mbscavenge()
|
||||
{
|
||||
bmalloc::api::scavenge();
|
||||
}
|
||||
|
||||
} // extern "C"
|
Loading…
Reference in New Issue
Block a user