diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..09e2781
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,8 @@
+# Contributing
+
+PyBee <3's contributions!
+
+Please be aware, PyBee operates under a Code of Conduct.
+
+See [CONTRIBUTING to PyBee](http://pybee.org/contributing) for details.
+
diff --git a/LICENSE b/LICENSE
index be2bd37..7c54523 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014 Russell Keith-Magee.
+Copyright (c) 2014-2016 Russell Keith-Magee.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
index ca7efde..0d9d196 100644
--- a/Makefile
+++ b/Makefile
@@ -1,60 +1,77 @@
-PROJECTDIR=$(shell pwd)
-
-BUILD_NUMBER=3
+#
+# Useful targets:
+# - all - build everything
+# - iOS - build everything for iOS
+# - tvOS - build everything for tvOS
+# - watchOS - build everything for watchOS
+# - OpenSSL.framework-iOS - build OpenSSL.framework for iOS
+# - OpenSSL.framework-tvOS - build OpenSSL.framework for tvOS
+# - OpenSSL.framework-watchOS - build OpenSSL.framework for watchOS
+# - BZip2-iOS - build BZip2 library for iOS
+# - BZip2-tvOS - build BZip2 library for tvOS
+# - BZip2-watchOS - build BZip2 library for watchOS
+# - XZ-iOS - build XZ library for iOS
+# - XZ-tvOS - build XZ library for tvOS
+# - XZ-watchOS - build XZ library for watchOS
+# - Python.framework-iOS - build Python.framework for iOS
+# - Python.framework-tvOS - build Python.framework for tvOS
+# - Python.framework-watchOS - build Python.framework for watchOS
+# - Python-host - build host python
+
+# Current director
+PROJECT_DIR=$(shell pwd)
+
+BUILD_NUMBER=5
# Version of packages that will be compiled by this meta-package
PYTHON_VERSION=3.4.2
+PYTHON_VER=$(basename $(PYTHON_VERSION))
OPENSSL_VERSION_NUMBER=1.0.2
-OPENSSL_REVISION=d
+OPENSSL_REVISION=f
OPENSSL_VERSION=$(OPENSSL_VERSION_NUMBER)$(OPENSSL_REVISION)
-# 32 bit iOS Simulator build commands and flags
-IOS_SIMULATOR_SDK_ROOT=$(shell xcrun --sdk iphonesimulator --show-sdk-path)
-IOS_SIMULATOR_CC=$(shell xcrun -find -sdk iphonesimulator clang) -arch i386 --sysroot=$(IOS_SIMULATOR_SDK_ROOT) -miphoneos-version-min=7.0
+BZIP2_VERSION=1.0.6
+
+XZ_VERSION=5.2.2
-# 64 bit iOS Simulator build commands and flags
-IOS_SIMULATOR_64_SDK_ROOT=$(shell xcrun --sdk iphonesimulator --show-sdk-path)
-IOS_SIMULATOR_64_CC=$(shell xcrun -find -sdk iphonesimulator clang) -arch x86_64 --sysroot=$(IOS_SIMULATOR_64_SDK_ROOT) -miphoneos-version-min=7.0
+# Supported OS
+OS=iOS tvOS watchOS
-# iOS ARMV7 build commands and flags
-IOS_ARMV7_SDK_ROOT=$(shell xcrun --sdk iphoneos --show-sdk-path)
-IOS_ARMV7_CC=$(shell xcrun -find -sdk iphoneos clang) -arch armv7 --sysroot=$(IOS_ARMV7_SDK_ROOT) -miphoneos-version-min=7.0
+# iOS targets
+TARGETS-iOS=iphonesimulator.x86_64 iphonesimulator.i386 iphoneos.armv7 iphoneos.armv7s iphoneos.arm64
+CFLAGS-iOS=-miphoneos-version-min=7.0
+CFLAGS-iphoneos.armv7=-fembed-bitcode
+CFLAGS-iphoneos.armv7s=-fembed-bitcode
+CFLAGS-iphoneos.arm64=-fembed-bitcode
-# iOS ARMV7S build commands and flags
-IOS_ARMV7S_SDK_ROOT=$(shell xcrun --sdk iphoneos --show-sdk-path)
-IOS_ARMV7S_CC=$(shell xcrun -find -sdk iphoneos clang) -arch armv7s --sysroot=$(IOS_ARMV7S_SDK_ROOT) -miphoneos-version-min=7.0
+# tvOS targets
+TARGETS-tvOS=appletvsimulator.x86_64 appletvos.arm64
+CFLAGS-tvOS=-mtvos-version-min=9.0
+CFLAGS-appletvos.arm64=-fembed-bitcode
+PYTHON_CONFIGURE-tvOS=ac_cv_func_sigaltstack=no
-# iOS ARM64 build commands and flags
-IOS_ARM64_SDK_ROOT=$(shell xcrun --sdk iphoneos --show-sdk-path)
-IOS_ARM64_CC=$(shell xcrun -find -sdk iphoneos clang) -arch arm64 --sysroot=$(IOS_ARM64_SDK_ROOT) -miphoneos-version-min=7.0
+# watchOS targets
+TARGETS-watchOS=watchsimulator.i386 watchos.armv7k
+CFLAGS-watchOS=-mwatchos-version-min=2.0
+CFLAGS-watchos.armv7k=-fembed-bitcode
+PYTHON_CONFIGURE-watchOS=ac_cv_func_sigaltstack=no
+# override machine types for arm64
+MACHINE_DETAILED-arm64=aarch64
+MACHINE_SIMPLE-arm64=arm
-all: Python-$(PYTHON_VERSION)-iOS-support.b$(BUILD_NUMBER).tar.gz
+all: $(foreach os,$(OS),$(os))
# Clean all builds
clean:
- rm -rf build dist Python-$(PYTHON_VERSION)-iOS-support.b$(BUILD_NUMBER).tar.gz
+ rm -rf build dist
# Full clean - includes all downloaded products
distclean: clean
rm -rf downloads
-Python-$(PYTHON_VERSION)-iOS-support.b$(BUILD_NUMBER).tar.gz: dist/OpenSSL.framework dist/Python.framework
- cd dist && tar zcvf ../Python-$(PYTHON_VERSION)-iOS-support.b$(BUILD_NUMBER).tar.gz Python.framework OpenSSL.framework
-
-###########################################################################
-# Working directories
-###########################################################################
-
-downloads:
- mkdir -p downloads
-
-build:
- mkdir -p build
-
-dist:
- mkdir -p dist
+downloads: downloads/openssl-$(OPENSSL_VERSION).tgz downloads/bzip2-$(BZIP2_VERSION).tgz downloads/xz-$(XZ_VERSION).tgz downloads/Python-$(PYTHON_VERSION).tgz
###########################################################################
# OpenSSL
@@ -64,183 +81,44 @@ dist:
# Clean the OpenSSL project
clean-OpenSSL:
- rm -rf build/openssl-$(OPENSSL_VERSION)
- rm -rf dist/OpenSSL.framework
+ rm -rf build/*/openssl-$(OPENSSL_VERSION)-* \
+ build/*/libssl.a build/*/libcrypto.a \
+ build/*/OpenSSL.framework
# Download original OpenSSL source code archive.
-downloads/openssl-$(OPENSSL_VERSION).tgz: downloads
+downloads/openssl-$(OPENSSL_VERSION).tgz:
+ mkdir -p downloads
-if [ ! -e downloads/openssl-$(OPENSSL_VERSION).tgz ]; then curl --fail -L http://openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz -o downloads/openssl-$(OPENSSL_VERSION).tgz; fi
if [ ! -e downloads/openssl-$(OPENSSL_VERSION).tgz ]; then curl --fail -L http://openssl.org/source/old/$(OPENSSL_VERSION_NUMBER)/openssl-$(OPENSSL_VERSION).tar.gz -o downloads/openssl-$(OPENSSL_VERSION).tgz; fi
-build/OpenSSL/ios-simulator-i386/libssl.a: build downloads/openssl-$(OPENSSL_VERSION).tgz
- # Unpack sources
- cd build && tar zxf ../downloads/openssl-$(OPENSSL_VERSION).tgz
- cd build && mv openssl-$(OPENSSL_VERSION) ios-simulator-i386
- mkdir -p build/OpenSSL
- cd build && mv ios-simulator-i386 OpenSSL
- # Tweak the Makefile to include sysroot and iOS minimum version
- cd build/OpenSSL/ios-simulator-i386 && \
- sed -ie "s!^CFLAG=!CFLAG=-isysroot $(IOS_SIMULATOR_SDK_ROOT) -arch i386 -miphoneos-version-min=7.0 !" Makefile
- # Configure the build
- cd build/OpenSSL/ios-simulator-i386 && \
- CC="$(IOS_SIMULATOR_CC)" \
- CROSS_TOP="$(dir $(IOS_SIMULATOR_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_SIMULATOR_SDK_ROOT))" \
- ./Configure iphoneos-cross --openssldir=$(PROJECTDIR)/build/OpenSSL/ios-simulator-i386
- # Make the build
- cd build/OpenSSL/ios-simulator-i386 && \
- CC="$(IOS_SIMULATOR_CC)" \
- CROSS_TOP="$(dir $(IOS_SIMULATOR_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_SIMULATOR_SDK_ROOT))" \
- make all
-
-build/OpenSSL/ios-simulator-x86_64/libssl.a: build downloads/openssl-$(OPENSSL_VERSION).tgz
- # Unpack sources
- cd build && tar zxf ../downloads/openssl-$(OPENSSL_VERSION).tgz
- cd build && mv openssl-$(OPENSSL_VERSION) ios-simulator-x86_64
- mkdir -p build/OpenSSL
- cd build && mv ios-simulator-x86_64 OpenSSL
- # Tweak the Makefile to include sysroot and iOS minimum version
- cd build/OpenSSL/ios-simulator-x86_64 && \
- sed -ie "s!^CFLAG=!CFLAG=-isysroot $(IOS_SIMULATOR_64_SDK_ROOT) -arch x86_64 -miphoneos-version-min=7.0 !" Makefile
- # Configure the build
- cd build/OpenSSL/ios-simulator-x86_64 && \
- CC="$(IOS_SIMULATOR_64_CC)" \
- CROSS_TOP="$(dir $(IOS_SIMULATOR_64_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_SIMULATOR_64_SDK_ROOT))" \
- ./Configure darwin64-x86_64-cc --openssldir=$(PROJECTDIR)/build/OpenSSL/ios-simulator-x86_64
- # Make the build
- cd build/OpenSSL/ios-simulator-x86_64 && \
- CC="$(IOS_SIMULATOR_64_CC)" \
- CROSS_TOP="$(dir $(IOS_SIMULATOR_64_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_SIMULATOR_64_SDK_ROOT))" \
- make all
-
-build/OpenSSL/ios-armv7/libssl.a: build downloads/openssl-$(OPENSSL_VERSION).tgz
- # Unpack sources
- cd build && tar zxf ../downloads/openssl-$(OPENSSL_VERSION).tgz
- cd build && mv openssl-$(OPENSSL_VERSION) ios-armv7
- mkdir -p build/OpenSSL
- cd build && mv ios-armv7 OpenSSL
- # Tweak the Makefile to include sysroot and iOS minimum version
- cd build/OpenSSL/ios-armv7 && \
- sed -ie "s!^CFLAG=!CFLAG=-isysroot $(IOS_ARMV7_SDK_ROOT) -arch armv7 -miphoneos-version-min=7.0 !" Makefile
- # Tweak ui_openssl.c
- cd build/OpenSSL/ios-armv7 && \
- sed -ie "s!static volatile sig_atomic_t intr_signal;!static volatile intr_signal;!" crypto/ui/ui_openssl.c
- # Configure the build
- cd build/OpenSSL/ios-armv7 && \
- CC="$(IOS_ARMV7_CC)" \
- CROSS_TOP="$(dir $(IOS_ARMV7_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_ARMV7_SDK_ROOT))" \
- ./Configure iphoneos-cross --openssldir=$(PROJECTDIR)/build/OpenSSL/ios-armv7
- # Make the build
- cd build/OpenSSL/ios-armv7 && \
- CC="$(IOS_ARMV7_CC)" \
- CROSS_TOP="$(dir $(IOS_ARMV7_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_ARMV7_SDK_ROOT))" \
- make all
-
-build/OpenSSL/ios-armv7s/libssl.a: build downloads/openssl-$(OPENSSL_VERSION).tgz
- # Unpack sources
- cd build && tar zxf ../downloads/openssl-$(OPENSSL_VERSION).tgz
- cd build && mv openssl-$(OPENSSL_VERSION) ios-armv7s
- mkdir -p build/OpenSSL
- cd build && mv ios-armv7s OpenSSL
- # Tweak the Makefile to include sysroot and iOS minimum version
- cd build/OpenSSL/ios-armv7s && \
- sed -ie "s!^CFLAG=!CFLAG=-isysroot $(IOS_ARMV7S_SDK_ROOT) -arch armv7s -miphoneos-version-min=7.0 !" Makefile
- # Tweak ui_openssl.c
- cd build/OpenSSL/ios-armv7s && \
- sed -ie "s!static volatile sig_atomic_t intr_signal;!static volatile intr_signal;!" crypto/ui/ui_openssl.c
- # Configure the build
- cd build/OpenSSL/ios-armv7s && \
- CC="$(IOS_ARMV7S_CC)" \
- CROSS_TOP="$(dir $(IOS_ARMV7S_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_ARMV7S_SDK_ROOT))" \
- ./Configure iphoneos-cross --openssldir=$(PROJECTDIR)/build/OpenSSL/ios-armv7s
- # Make the build
- cd build/OpenSSL/ios-armv7s && \
- CC="$(IOS_ARMV7S_CC)" \
- CROSS_TOP="$(dir $(IOS_ARMV7S_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_ARMV7S_SDK_ROOT))" \
- make all
-build/OpenSSL/ios-arm64/libssl.a: build downloads/openssl-$(OPENSSL_VERSION).tgz
- # Unpack sources
- cd build && tar zxf ../downloads/openssl-$(OPENSSL_VERSION).tgz
- cd build && mv openssl-$(OPENSSL_VERSION) ios-arm64
- mkdir -p build/OpenSSL
- cd build && mv ios-arm64 OpenSSL
- # Tweak the Makefile to include sysroot and iOS minimum version
- cd build/OpenSSL/ios-arm64 && \
- sed -ie "s!^CFLAG=!CFLAG=-isysroot $(IOS_ARM64_SDK_ROOT) -arch arm64 -miphoneos-version-min=7.0 !" Makefile
- # Tweak ui_openssl.c
- cd build/OpenSSL/ios-arm64 && \
- sed -ie "s!static volatile sig_atomic_t intr_signal;!static volatile intr_signal;!" crypto/ui/ui_openssl.c
- # Configure the build
- cd build/OpenSSL/ios-arm64 && \
- CC="$(IOS_ARM64_CC)" \
- CROSS_TOP="$(dir $(IOS_ARM64_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_ARM64_SDK_ROOT))" \
- ./Configure iphoneos-cross --openssldir=$(PROJECTDIR)/build/OpenSSL/ios-arm64
- # Make the build
- cd build/OpenSSL/ios-arm64 && \
- CC="$(IOS_ARM64_CC)" \
- CROSS_TOP="$(dir $(IOS_ARM64_SDK_ROOT)).." \
- CROSS_SDK="$(notdir $(IOS_ARM64_SDK_ROOT))" \
- make all
+###########################################################################
+# BZip2
+###########################################################################
-build/OpenSSL/libssl.a: \
- build/OpenSSL/ios-simulator-i386/libssl.a \
- build/OpenSSL/ios-simulator-x86_64/libssl.a \
- build/OpenSSL/ios-armv7/libssl.a \
- build/OpenSSL/ios-armv7s/libssl.a \
- build/OpenSSL/ios-arm64/libssl.a
- cd build/OpenSSL && \
- lipo -create \
- ios-simulator-i386/libssl.a \
- ios-simulator-x86_64/libssl.a \
- ios-armv7/libssl.a \
- ios-armv7s/libssl.a \
- ios-arm64/libssl.a \
- -output libssl.a
-
-build/OpenSSL/libcrypto.a: \
- build/OpenSSL/ios-simulator-i386/libssl.a \
- build/OpenSSL/ios-simulator-x86_64/libssl.a \
- build/OpenSSL/ios-armv7/libssl.a \
- build/OpenSSL/ios-armv7s/libssl.a \
- build/OpenSSL/ios-arm64/libssl.a
- cd build/OpenSSL && \
- lipo -create \
- ios-simulator-i386/libcrypto.a \
- ios-simulator-x86_64/libcrypto.a \
- ios-armv7/libcrypto.a \
- ios-armv7s/libcrypto.a \
- ios-arm64/libcrypto.a \
- -output libcrypto.a
-
-dist/OpenSSL.framework: dist build/OpenSSL/libssl.a build/OpenSSL/libcrypto.a
- # Create framework directory structure
- cd dist && mkdir -p OpenSSL.framework
- cd dist && mkdir -p OpenSSL.framework/Versions/$(OPENSSL_VERSION)/
- cd dist/OpenSSL.framework/Versions && ln -fs $(OPENSSL_VERSION) Current
+# Clean the bzip2 project
+clean-bzip2:
+ rm -rf build/*/bzip2-$(BZIP2_VERSION)-* \
+ build/*/bzip2
- # Copy the headers (use the version from the x86_64 simulator because reasons)
- cp -r build/OpenSSL/ios-simulator-x86_64/include dist/OpenSSL.framework/Versions/Current/Headers
+# Download original OpenSSL source code archive.
+downloads/bzip2-$(BZIP2_VERSION).tgz:
+ mkdir -p downloads
+ if [ ! -e downloads/bzip2-$(BZIP2_VERSION).tgz ]; then curl --fail -L http://www.bzip.org/$(BZIP2_VERSION)/bzip2-$(BZIP2_VERSION).tar.gz -o downloads/bzip2-$(BZIP2_VERSION).tgz; fi
- # Link the current Headers to the top level
- cd dist/OpenSSL.framework && ln -fs Versions/Current/Headers
+###########################################################################
+# XZ (LZMA)
+###########################################################################
- # Create the fat library
- libtool -no_warning_for_no_symbols -static \
- -o dist/OpenSSL.framework/Versions/Current/OpenSSL \
- build/OpenSSL/libcrypto.a \
- build/OpenSSL/libssl.a
+# Clean the XZ project
+clean-xz:
+ rm -rf build/*/xz-$(XZ_VERSION)-* \
+ build/*/xz
- # Link the fat Library to the top level
- cd dist/OpenSSL.framework && ln -fs Versions/Current/OpenSSL
+# Download original OpenSSL source code archive.
+downloads/xz-$(XZ_VERSION).tgz:
+ mkdir -p downloads
+ if [ ! -e downloads/xz-$(XZ_VERSION).tgz ]; then curl --fail -L http://tukaani.org/xz/xz-$(XZ_VERSION).tar.gz -o downloads/xz-$(XZ_VERSION).tgz; fi
###########################################################################
# Python
@@ -248,23 +126,270 @@ dist/OpenSSL.framework: dist build/OpenSSL/libssl.a build/OpenSSL/libcrypto.a
# Clean the Python project
clean-Python:
- rm -rf build/Python-$(PYTHON_VERSION)
- rm -rf build/python
- rm -rf dist/Python.framework
+ rm -rf build/Python-$(PYTHON_VERSION)-host build/*/Python-$(PYTHON_VERSION)-* \
+ build/*/libpython$(PYTHON_VER).a build/*/pyconfig-*.h \
+ build/*/Python.framework
# Download original Python source code archive.
-downloads/Python-$(PYTHON_VERSION).tgz: downloads
+downloads/Python-$(PYTHON_VERSION).tgz:
+ mkdir -p downloads
if [ ! -e downloads/Python-$(PYTHON_VERSION).tgz ]; then curl -L https://www.python.org/ftp/python/$(PYTHON_VERSION)/Python-$(PYTHON_VERSION).tgz > downloads/Python-$(PYTHON_VERSION).tgz; fi
-# build/Python-$(PYTHON_VERSION)/Python.framework: build dist/OpenSSL.framework downloads/Python-$(PYTHON_VERSION).tgz
-build/Python-$(PYTHON_VERSION)/Python.framework: build downloads/Python-$(PYTHON_VERSION).tgz
+PYTHON_DIR-host=build/Python-$(PYTHON_VERSION)-host
+PYTHON_HOST=$(PYTHON_DIR-host)/dist/bin/python$(PYTHON_VER)
+
+Python-host: $(PYTHON_HOST)
+
+# Unpack host Python
+$(PYTHON_DIR-host)/Makefile: downloads/Python-$(PYTHON_VERSION).tgz
+ # Unpack host Python
+ mkdir -p $(PYTHON_DIR-host)
+ tar zxf downloads/Python-$(PYTHON_VERSION).tgz --strip-components 1 -C $(PYTHON_DIR-host)
+ # Configure host Python
+ cd $(PYTHON_DIR-host) && ./configure --prefix=$(PROJECT_DIR)/$(PYTHON_DIR-host)/dist --without-ensurepip
+
+# Build host Python
+$(PYTHON_DIR-host)/dist/bin/python$(PYTHON_VER): $(PYTHON_DIR-host)/Makefile
+ # Build host Python
+ make -C $(PYTHON_DIR-host) all install
+
+#
+# Build for specified target (from $(TARGETS))
+#
+# Parameters:
+# - $1 - target
+# - $2 - OS
+define build-target
+ARCH-$1=$$(subst .,,$$(suffix $1))
+ifdef MACHINE_DETAILED-$$(ARCH-$1)
+MACHINE_DETAILED-$1=$$(MACHINE_DETAILED-$$(ARCH-$1))
+else
+MACHINE_DETAILED-$1=$$(ARCH-$1)
+endif
+ifdef MACHINE_SIMPLE-$$(ARCH-$1)
+MACHINE_SIMPLE-$1=$$(MACHINE_SIMPLE-$$(ARCH-$1))
+else
+MACHINE_SIMPLE-$1=$$(ARCH-$1)
+endif
+SDK-$1=$$(basename $1)
+
+SDK_ROOT-$1=$$(shell xcrun --sdk $$(SDK-$1) --show-sdk-path)
+CC-$1=xcrun --sdk $$(SDK-$1) clang\
+ -arch $$(ARCH-$1) --sysroot=$$(SDK_ROOT-$1) $$(CFLAGS-$2) $$(CFLAGS-$1)
+LDFLAGS-$1=-arch $$(ARCH-$1) -isysroot=$$(SDK_ROOT-$1)
+
+OPENSSL_DIR-$1=build/$2/openssl-$(OPENSSL_VERSION)-$1
+BZIP2_DIR-$1=build/$2/bzip2-$(BZIP2_VERSION)-$1
+XZ_DIR-$1=build/$2/xz-$(XZ_VERSION)-$1
+PYTHON_DIR-$1=build/$2/Python-$(PYTHON_VERSION)-$1
+pyconfig.h-$1=pyconfig-$$(ARCH-$1).h
+
+# Unpack OpenSSL
+$$(OPENSSL_DIR-$1)/Makefile: downloads/openssl-$(OPENSSL_VERSION).tgz
# Unpack sources
- cd build && tar zxf ../downloads/Python-$(PYTHON_VERSION).tgz
- # Apply patches
- cd build/Python-$(PYTHON_VERSION) && patch -p1 < ../../patch/Python/Python.patch
- cd build/Python-$(PYTHON_VERSION) && cp ../../patch/Python/Setup.embedded Modules/Setup.embedded
- # Configure and make the build
- cd build/Python-$(PYTHON_VERSION)/iOS && make
-
-dist/Python.framework: dist build/Python-$(PYTHON_VERSION)/Python.framework
- cd dist && mv ../build/Python-$(PYTHON_VERSION)/Python.framework .
+ mkdir -p $$(OPENSSL_DIR-$1)
+ tar zxf downloads/openssl-$(OPENSSL_VERSION).tgz --strip-components 1 -C $$(OPENSSL_DIR-$1)
+ifeq ($$(findstring simulator,$$(SDK-$1)),)
+ # Tweak ui_openssl.c
+ sed -ie "s!static volatile sig_atomic_t intr_signal;!static volatile intr_signal;!" $$(OPENSSL_DIR-$1)/crypto/ui/ui_openssl.c
+endif
+ifeq ($$(findstring iphone,$$(SDK-$1)),)
+ # Patch apps/speed.c to not use fork() since it's not available on tvOS
+ sed -ie 's/define HAVE_FORK 1/define HAVE_FORK 0/' $$(OPENSSL_DIR-$1)/apps/speed.c
+ # Patch Configure to build for tvOS or watchOS, not iOS
+ LC_ALL=C sed -ie 's/-D_REENTRANT:iOS/-D_REENTRANT:$2/' $$(OPENSSL_DIR-$1)/Configure
+endif
+ # Configure the build
+ cd $$(OPENSSL_DIR-$1) && \
+ CC="$$(CC-$1)" \
+ CROSS_TOP="$$(dir $$(SDK_ROOT-$1)).." \
+ CROSS_SDK="$$(notdir $$(SDK_ROOT-$1))" \
+ ./Configure iphoneos-cross no-asm --openssldir=$(PROJECT_DIR)/$$(OPENSSL_DIR-$1)
+
+# Build OpenSSL
+$$(OPENSSL_DIR-$1)/libssl.a $$(OPENSSL_DIR-$1)/libcrypto.a: $$(OPENSSL_DIR-$1)/Makefile
+ # Make the build
+ cd $$(OPENSSL_DIR-$1) && \
+ CC="$$(CC-$1)" \
+ CROSS_TOP="$$(dir $$(SDK_ROOT-$1)).." \
+ CROSS_SDK="$$(notdir $$(SDK_ROOT-$1))" \
+ make all
+
+# Unpack BZip2
+$$(BZIP2_DIR-$1)/Makefile: downloads/bzip2-$(BZIP2_VERSION).tgz
+ # Unpack sources
+ mkdir -p $$(BZIP2_DIR-$1)
+ tar zxf downloads/bzip2-$(BZIP2_VERSION).tgz --strip-components 1 -C $$(BZIP2_DIR-$1)
+ # Patch sources to use correct compiler
+ sed -ie 's#CC=gcc#CC=$$(CC-$1)#' $$(BZIP2_DIR-$1)/Makefile
+ # Patch sources to use correct install directory
+ sed -ie 's#PREFIX=/usr/local#PREFIX=$(PROJECT_DIR)/build/$2/bzip2#' $$(BZIP2_DIR-$1)/Makefile
+
+# Build BZip2
+$$(BZIP2_DIR-$1)/libbz2.a: $$(BZIP2_DIR-$1)/Makefile
+ cd $$(BZIP2_DIR-$1) && make install
+
+# Unpack XZ
+$$(XZ_DIR-$1)/Makefile: downloads/xz-$(XZ_VERSION).tgz
+ # Unpack sources
+ mkdir -p $$(XZ_DIR-$1)
+ tar zxf downloads/xz-$(XZ_VERSION).tgz --strip-components 1 -C $$(XZ_DIR-$1)
+ # Configure the build
+ cd $$(XZ_DIR-$1) && ./configure \
+ CC="$$(CC-$1)" \
+ LDFLAGS="$$(LDFLAGS-$1)" \
+ --disable-shared --enable-static \
+ --host=$$(MACHINE_SIMPLE-$1)-apple-darwin \
+ --prefix=$(PROJECT_DIR)/build/$2/xz
+
+# Build XZ
+$$(XZ_DIR-$1)/src/liblzma/.libs/liblzma.a: $$(XZ_DIR-$1)/Makefile
+ cd $$(XZ_DIR-$1) && make && make install
+
+# Unpack Python
+$$(PYTHON_DIR-$1)/Makefile: downloads/Python-$(PYTHON_VERSION).tgz $(PYTHON_HOST)
+ # Unpack target Python
+ mkdir -p $$(PYTHON_DIR-$1)
+ tar zxf downloads/Python-$(PYTHON_VERSION).tgz --strip-components 1 -C $$(PYTHON_DIR-$1)
+ # Apply target Python patches
+ cd $$(PYTHON_DIR-$1) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch
+ cp -f $(PROJECT_DIR)/patch/Python/Setup.embedded $$(PYTHON_DIR-$1)/Modules/Setup.embedded
+ # Configure target Python
+ cd $$(PYTHON_DIR-$1) && PATH=$(PROJECT_DIR)/$(PYTHON_DIR-host)/dist/bin:$(PATH) ./configure \
+ CC="$$(CC-$1)" LD="$$(CC-$1)" \
+ --host=$$(MACHINE_DETAILED-$1)-apple-ios --build=x86_64-apple-darwin$(shell uname -r) \
+ --prefix=$(PROJECT_DIR)/$$(PYTHON_DIR-$1)/dist \
+ --without-pymalloc --without-doc-strings --disable-ipv6 --without-ensurepip \
+ ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no \
+ $$(PYTHON_CONFIGURE-$2)
+
+# Build Python
+$$(PYTHON_DIR-$1)/dist/lib/libpython$(PYTHON_VER).a: build/$2/OpenSSL.framework build/$2/bzip2/lib/libbz2.a build/$2/xz/lib/liblzma.a $$(PYTHON_DIR-$1)/Makefile
+ # Build target Python
+ cd $$(PYTHON_DIR-$1) && PATH=$(PROJECT_DIR)/$(PYTHON_DIR-host)/dist/bin:$(PATH) make all install
+
+build/$2/$$(pyconfig.h-$1): $$(PYTHON_DIR-$1)/dist/include/python$(PYTHON_VER)/pyconfig.h
+ cp -f $$^ $$@
+
+# Dump vars (for test)
+vars-$1:
+ @echo "ARCH-$1: $$(ARCH-$1)"
+ @echo "MACHINE_DETAILED-$1: $$(MACHINE_DETAILED-$1)"
+ @echo "SDK-$1: $$(SDK-$1)"
+ @echo "SDK_ROOT-$1: $$(SDK_ROOT-$1)"
+ @echo "CC-$1: $$(CC-$1)"
+endef
+
+#
+# Install target pyconfig.h
+# Parameters:
+# - $1 - target
+# - $2 - framework directory
+define install-target-pyconfig
+endef
+
+#
+# Build for specified OS (from $(OS))
+# Parameters:
+# - $1 - OS
+define build
+$$(foreach target,$$(TARGETS-$1),$$(eval $$(call build-target,$$(target),$1)))
+
+OPENSSL_FRAMEWORK-$1=build/$1/OpenSSL.framework
+BZIP2_LIB-$1=build/$1/bzip2/lib/libbz2.a
+XZ_LIB-$1=build/$1/xz/lib/liblzma.a
+PYTHON_FRAMEWORK-$1=build/$1/Python.framework
+PYTHON_RESOURCES-$1=$$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Resources
+
+$1: dist/Python-$(PYTHON_VERSION)-$1-support.b$(BUILD_NUMBER).tar.gz
+
+clean-$1:
+ rm -rf build/$1
+
+dist/Python-$(PYTHON_VERSION)-$1-support.b$(BUILD_NUMBER).tar.gz: $$(OPENSSL_FRAMEWORK-$1) $$(PYTHON_FRAMEWORK-$1)
+ mkdir -p dist
+ tar zcvf $$@ -C build/$1 $$(notdir $$^)
+
+OpenSSL.framework-$1: $$(OPENSSL_FRAMEWORK-$1)
+
+# Build OpenSSL.framework
+$$(OPENSSL_FRAMEWORK-$1): build/$1/libssl.a build/$1/libcrypto.a
+ # Create framework directory structure
+ mkdir -p $$(OPENSSL_FRAMEWORK-$1)/Versions/$(OPENSSL_VERSION)
+
+ # Copy the headers (use the version from the simulator because reasons)
+ cp -f -r $$(OPENSSL_DIR-$$(firstword $$(TARGETS-$1)))/include $$(OPENSSL_FRAMEWORK-$1)/Versions/$(OPENSSL_VERSION)/Headers
+
+ # Create the fat library
+ xcrun libtool -no_warning_for_no_symbols -static \
+ -o $$(OPENSSL_FRAMEWORK-$1)/Versions/$(OPENSSL_VERSION)/OpenSSL $$^
+
+ # Create symlinks
+ ln -fs $(OPENSSL_VERSION) $$(OPENSSL_FRAMEWORK-$1)/Versions/Current
+ ln -fs Versions/Current/Headers $$(OPENSSL_FRAMEWORK-$1)
+ ln -fs Versions/Current/OpenSSL $$(OPENSSL_FRAMEWORK-$1)
+
+build/$1/libssl.a: $$(foreach target,$$(TARGETS-$1),$$(OPENSSL_DIR-$$(target))/libssl.a)
+ mkdir -p build/$1
+ xcrun lipo -create -output $$@ $$^
+
+build/$1/libcrypto.a: $$(foreach target,$$(TARGETS-$1),$$(OPENSSL_DIR-$$(target))/libcrypto.a)
+ mkdir -p build/$1
+ xcrun lipo -create -output $$@ $$^
+
+BZip2-$1: $$(BZIP2_LIB-$1)
+
+build/$1/bzip2/lib/libbz2.a: $$(foreach target,$$(TARGETS-$1),$$(BZIP2_DIR-$$(target))/libbz2.a)
+ mkdir -p build/$1/bzip2/lib
+ xcrun lipo -create -o $$(BZIP2_LIB-$1) $$^
+
+XZ-$1: $$(XZ_LIB-$1)
+
+build/$1/xz/lib/liblzma.a: $$(foreach target,$$(TARGETS-$1),$$(XZ_DIR-$$(target))/src/liblzma/.libs/liblzma.a)
+ mkdir -p build/$1/xz/lib
+ xcrun lipo -create -o $$(XZ_LIB-$1) $$^
+
+Python.framework-$1: $$(PYTHON_FRAMEWORK-$1)
+
+# Build Python.framework
+$$(PYTHON_FRAMEWORK-$1): build/$1/libpython$(PYTHON_VER).a $$(foreach target,$$(TARGETS-$1),build/$1/$$(pyconfig.h-$$(target)))
+ mkdir -p $$(PYTHON_RESOURCES-$1)/include/python$(PYTHON_VER)
+
+ # Copy the headers. The headers are the same for every platform, except for pyconfig.h
+ cp -f -r $$(PYTHON_DIR-$$(firstword $$(TARGETS-$1)))/dist/include/python$(PYTHON_VER) $$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Headers
+ cp -f $$(filter %.h,$$^) $$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Headers
+ cp -f $$(PYTHON_DIR-$$(firstword $$(TARGETS-$1)))/iOS/include/pyconfig.h $$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Headers
+
+ # Copy Python.h and pyconfig.h into the resources include directory
+ cp -f -r $$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Headers/pyconfig*.h $$(PYTHON_RESOURCES-$1)/include/python$(PYTHON_VER)
+ cp -f -r $$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Headers/Python.h $$(PYTHON_RESOURCES-$1)/include/python$(PYTHON_VER)
+
+ # Copy the standard library from the simulator build
+ifneq ($(TEST),)
+ cp -f -r $$(PYTHON_DIR-$$(firstword $$(TARGETS-$1)))/dist/lib $$(PYTHON_RESOURCES-$1)
+ # Remove the pieces of the resources directory that aren't needed:
+ rm -f $$(PYTHON_RESOURCES-$1)/lib/libpython$(PYTHON_VER).a
+ rm -rf $$(PYTHON_RESOURCES-$1)/lib/pkgconfig
+else
+ mkdir -p $$(PYTHON_RESOURCES-$1)/lib
+ cd $$(PYTHON_DIR-$$(firstword $$(TARGETS-$1)))/dist/lib/python$(PYTHON_VER) && \
+ zip -x@$(PROJECT_DIR)/patch/Python/lib-exclude.lst -r $(PROJECT_DIR)/$$(PYTHON_RESOURCES-$1)/lib/python$(subst .,,$(PYTHON_VER)) *
+endif
+
+ # Copy fat library
+ cp -f $$(filter %.a,$$^) $$(PYTHON_FRAMEWORK-$1)/Versions/$(PYTHON_VER)/Python
+
+ # Create symlinks
+ ln -fs $(PYTHON_VER) $$(PYTHON_FRAMEWORK-$1)/Versions/Current
+ ln -fs Versions/Current/Headers $$(PYTHON_FRAMEWORK-$1)
+ ln -fs Versions/Current/Resources $$(PYTHON_FRAMEWORK-$1)
+ ln -fs Versions/Current/Python $$(PYTHON_FRAMEWORK-$1)
+
+# Build libpython fat library
+build/$1/libpython$(PYTHON_VER).a: $$(foreach target,$$(TARGETS-$1),$$(PYTHON_DIR-$$(target))/dist/lib/libpython$(PYTHON_VER).a)
+ # Create a fat binary for the libPython library
+ mkdir -p build/$1
+ xcrun lipo -create -output $$@ $$^
+endef
+
+$(foreach os,$(OS),$(eval $(call build,$(os))))
diff --git a/README.rst b/README.rst
index 20cfdb8..34308bd 100644
--- a/README.rst
+++ b/README.rst
@@ -1,58 +1,83 @@
+WARNING: This project is DEPRECATED
+-----------------------------------
+
+It has been replaced by the multi-platform `Python-Apple-support`_ package
+
+.. _Python-Apple-support: https://github.com/pybee/Python-Apple-support
+
Python iOS Support
==================
This is a meta-package for building a version of Python that can be embedded
-into an iOS project.
+into an iOS, tvOS or watchOS project.
It works by downloading, patching, and building a fat binary OpenSSL and
Python, and packaging them both in iOS Framework format.
The binaries support the ``$(ARCHS_STANDARD)`` set - that is, armv7 and
-arm64. This should enable the code to run on:
+arm64 for iOS devices, arm64 for appleTV devices, and armv7k for watchOS.
+This should enable the code to run on:
* iPhone
- iPhone 4s
- iPhone 5
+ - iPhone 5c
- iPhone 5s
- iPhone 6
- iPhone 6 Plus
+ - iPhone 6s
+ - iPhone 6s Plus
+* iPad Pro
* iPad
- iPad 2
- iPad (3rd gen)
- iPad (4th gen)
- iPad Air
+ - iPad Air 2
- iPad retina
* iPad Mini
- iPad Mini (1st gen)
- - iPad Mini (2nd gen)
+ - iPad Mini 2
+ - iPad Mini 3
+ - iPad Mini 4
* iPod Touch
- iPod Touch (4th gen)
- iPod Touch (5th gen)
+ - iPod Touch (6th gen)
+* Apple TV
+ - 4th gen
+* Apple Watch
-This repository branch builds a packaged version of **Python 3.4.2**.
+This repository branch builds a packaged version of **Python 3.5.1**.
Other Python versions are available by cloning other branches of the main
repository.
Quickstart
----------
-Pre-built versions of the frameworks can be downloaded_, and added to
-your iOS project.
+Pre-built versions of the frameworks can be downloaded `for iOS`_,
+`for tvOS`_, and `for watchOS`_, and added to your project.
Alternatively, to build the frameworks on your own, download/clone this
repository, and then in the root directory, and run:
- $ make
+* `make` (or `make all`) to build everything.
+* `make iOS` to build everything for iOS.
+* `make tvOS` to build everything for tvOS.
+* `make watchOS` to build everything for watchOS.
This should:
1. Download the original source packages
-2. Patch them as required for iOS compatibility
-3. Build the packages as iOS frameworks.
+2. Patch them as required for compatibility with the selected OS
+3. Build the packages as XCode-compatible frameworks.
-The build products will be in the `build` directory.
+The build products will be in the `build` directory; the compiled frameworks
+will be in the `dist` directory.
-.. _downloaded: https://github.com/pybee/Python-iOS-support/releases/download/3.4.2-b2/Python-3.4.2-iOS-support.b2.tar.gz
+.. _for iOS: https://github.com/pybee/Python-iOS-support/releases/download/3.4.2-b5/Python-3.4.2-iOS-support.b5.tar.gz
+.. _for tvOS: https://github.com/pybee/Python-iOS-support/releases/download/3.4.2-b5/Python-3.4.2-iOS-support.b5.tar.gz
+.. _for watchOS: https://github.com/pybee/Python-iOS-support/releases/download/3.4.2-b5/Python-3.4.2-iOS-support.b5.tar.gz
Acknowledgements
----------------
diff --git a/patch/Python/Python.patch b/patch/Python/Python.patch
index 6ff42a5..d114418 100644
--- a/patch/Python/Python.patch
+++ b/patch/Python/Python.patch
@@ -13375,7 +13375,7 @@ diff -Nru orig/Lib/webbrowser.py modified/Lib/webbrowser.py
# platform are, allow user to override them with the BROWSER variable.
diff -Nru orig/Modules/Setup.embedded modified/Modules/Setup.embedded
--- orig/Modules/Setup.embedded 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/Setup.embedded 2015-06-28 15:00:41.000000000 +0800
++++ modified/Modules/Setup.embedded 2015-07-04 23:36:43.000000000 +0800
@@ -0,0 +1,91 @@
+#####################################################################
+# Static compilation instructions for all binary modules.
@@ -13408,6 +13408,16 @@ diff -Nru orig/Modules/Setup.embedded modified/Modules/Setup.embedded
+_sha256 sha256module.c
+_sha512 sha512module.c
+_socket socketmodule.c
++_sqlite3 -I$(srcdir)/Modules/_sqlite -DMODULE_NAME='\"sqlite3\"' -DSQLITE_OMIT_LOAD_EXTENSION -lsqlite3 \
++ _sqlite/cache.c \
++ _sqlite/connection.c \
++ _sqlite/cursor.c \
++ _sqlite/microprotocols.c \
++ _sqlite/module.c \
++ _sqlite/prepare_protocol.c \
++ _sqlite/row.c \
++ _sqlite/statement.c \
++ _sqlite/util.c
+_struct _struct.c
+array arraymodule.c
+audioop audioop.c
@@ -13426,16 +13436,6 @@ diff -Nru orig/Modules/Setup.embedded modified/Modules/Setup.embedded
+ -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI
+resource resource.c
+select selectmodule.c
-+_sqlite3 -I$(srcdir)/Modules/_sqlite -DMODULE_NAME='\"sqlite3\"' -DSQLITE_OMIT_LOAD_EXTENSION -lsqlite3 \
-+ _sqlite/cache.c \
-+ _sqlite/connection.c \
-+ _sqlite/cursor.c \
-+ _sqlite/microprotocols.c \
-+ _sqlite/module.c \
-+ _sqlite/prepare_protocol.c \
-+ _sqlite/row.c \
-+ _sqlite/statement.c \
-+ _sqlite/util.c
+syslog syslogmodule.c
+termios termios.c
+time timemodule.c
@@ -13470,8 +13470,8 @@ diff -Nru orig/Modules/Setup.embedded modified/Modules/Setup.embedded
+#spwd spwdmodule.c
diff -Nru orig/Modules/Setup.ios-aarch64 modified/Modules/Setup.ios-aarch64
--- orig/Modules/Setup.ios-aarch64 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/Setup.ios-aarch64 2015-04-26 11:31:03.000000000 +0800
-@@ -0,0 +1,34 @@
++++ modified/Modules/Setup.ios-aarch64 2015-12-20 23:03:15.000000000 +0800
+@@ -0,0 +1,35 @@
+
+#####################################################################
+# iOS ARM64: Platform specific configuration
@@ -13481,13 +13481,14 @@ diff -Nru orig/Modules/Setup.ios-aarch64 modified/Modules/Setup.ios-aarch64
+ _ctypes/callproc.c \
+ _ctypes/stgdict.c \
+ _ctypes/cfield.c \
-+ _ctypes/libffi_ios_aarch64/prep_cif.c \
-+ _ctypes/libffi_ios_aarch64/raw_api.c \
-+ _ctypes/libffi_ios_aarch64/java_raw_api.c \
-+ _ctypes/libffi_ios_aarch64/closures.c \
-+ _ctypes/libffi_ios_aarch64/aarch64/ffi_arm64.c \
-+ _ctypes/libffi_ios_aarch64/aarch64/sysv_arm64.S \
-+ -I$(srcdir)/Modules/_ctypes/libffi_ios_aarch64/include
++ _ctypes/libffi_ios/prep_cif.c \
++ _ctypes/libffi_ios/types.c \
++ _ctypes/libffi_ios/raw_api.c \
++ _ctypes/libffi_ios/java_raw_api.c \
++ _ctypes/libffi_ios/closures.c \
++ _ctypes/libffi_ios/aarch64/ffi_arm64.c \
++ _ctypes/libffi_ios/aarch64/sysv_arm64.S \
++ -I$(srcdir)/Modules/_ctypes/libffi_ios/include
+
+_decimal _decimal/_decimal.c \
+ _decimal/libmpdec/basearith.c \
@@ -13508,8 +13509,8 @@ diff -Nru orig/Modules/Setup.ios-aarch64 modified/Modules/Setup.ios-aarch64
+ -DCONFIG_64=1 -DANSI=1 -DHAVE_UINT128_T=1
diff -Nru orig/Modules/Setup.ios-arm modified/Modules/Setup.ios-arm
--- orig/Modules/Setup.ios-arm 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/Setup.ios-arm 2015-04-26 11:31:08.000000000 +0800
-@@ -0,0 +1,35 @@
++++ modified/Modules/Setup.ios-arm 2015-12-20 23:02:39.000000000 +0800
+@@ -0,0 +1,36 @@
+
+#####################################################################
+# iOS ARMv7: Platform specific configuration
@@ -13520,6 +13521,7 @@ diff -Nru orig/Modules/Setup.ios-arm modified/Modules/Setup.ios-arm
+ _ctypes/stgdict.c \
+ _ctypes/cfield.c \
+ _ctypes/libffi_ios/prep_cif.c \
++ _ctypes/libffi_ios/types.c \
+ _ctypes/libffi_ios/raw_api.c \
+ _ctypes/libffi_ios/java_raw_api.c \
+ _ctypes/libffi_ios/closures.c \
@@ -13547,7 +13549,7 @@ diff -Nru orig/Modules/Setup.ios-arm modified/Modules/Setup.ios-arm
+ -DCONFIG_32=1 -DANSI=1
diff -Nru orig/Modules/Setup.ios-i386 modified/Modules/Setup.ios-i386
--- orig/Modules/Setup.ios-i386 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/Setup.ios-i386 2015-04-26 11:31:06.000000000 +0800
++++ modified/Modules/Setup.ios-i386 2015-12-20 23:01:44.000000000 +0800
@@ -0,0 +1,35 @@
+
+#####################################################################
@@ -13559,12 +13561,12 @@ diff -Nru orig/Modules/Setup.ios-i386 modified/Modules/Setup.ios-i386
+ _ctypes/stgdict.c \
+ _ctypes/cfield.c \
+ _ctypes/libffi_ios/prep_cif.c \
++ _ctypes/libffi_ios/types.c \
+ _ctypes/libffi_ios/raw_api.c \
+ _ctypes/libffi_ios/java_raw_api.c \
+ _ctypes/libffi_ios/closures.c \
+ _ctypes/libffi_ios/x86/ffi_i386.c \
-+ _ctypes/libffi_ios/x86/darwin_i386.S \
-+ _ctypes/libffi_ios/x86/win32_i386.S \
++ _ctypes/libffi_ios/x86/sysv_i386.S \
+ -I$(srcdir)/Modules/_ctypes/libffi_ios/include
+
+_decimal _decimal/_decimal.c \
@@ -13586,8 +13588,8 @@ diff -Nru orig/Modules/Setup.ios-i386 modified/Modules/Setup.ios-i386
+ -DCONFIG_32=1 -DANSI=1
diff -Nru orig/Modules/Setup.ios-x86_64 modified/Modules/Setup.ios-x86_64
--- orig/Modules/Setup.ios-x86_64 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/Setup.ios-x86_64 2015-04-26 11:31:11.000000000 +0800
-@@ -0,0 +1,34 @@
++++ modified/Modules/Setup.ios-x86_64 2015-12-20 23:01:43.000000000 +0800
+@@ -0,0 +1,35 @@
+
+#####################################################################
+# iOS x86_64 Simulator: Platform specific configuration
@@ -13598,11 +13600,12 @@ diff -Nru orig/Modules/Setup.ios-x86_64 modified/Modules/Setup.ios-x86_64
+ _ctypes/stgdict.c \
+ _ctypes/cfield.c \
+ _ctypes/libffi_ios/prep_cif.c \
++ _ctypes/libffi_ios/types.c \
+ _ctypes/libffi_ios/raw_api.c \
+ _ctypes/libffi_ios/java_raw_api.c \
+ _ctypes/libffi_ios/closures.c \
+ _ctypes/libffi_ios/x86/ffi64_x86_64.c \
-+ _ctypes/libffi_ios/x86/darwin64_x86_64.S \
++ _ctypes/libffi_ios/x86/unix64_x86_64.S \
+ -I$(srcdir)/Modules/_ctypes/libffi_ios/include
+
+_decimal _decimal/_decimal.c \
@@ -13649,12 +13652,12 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/LICENSE modified/Modules/_ctypes/libff
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff -Nru orig/Modules/_ctypes/libffi_ios/README modified/Modules/_ctypes/libffi_ios/README
--- orig/Modules/_ctypes/libffi_ios/README 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/README 2015-04-26 07:29:13.000000000 +0800
-@@ -0,0 +1,447 @@
++++ modified/Modules/_ctypes/libffi_ios/README 2015-12-21 09:55:54.000000000 +0800
+@@ -0,0 +1,450 @@
+Status
+======
+
-+libffi-3.2.1 was released on November 12, 2014. Check the libffi web
++libffi-4?? was released on TBD. Check the libffi web
+page for updates: .
+
+
@@ -13835,6 +13838,9 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/README modified/Modules/_ctypes/libffi
+
+See the git log for details at http://github.com/atgreen/libffi.
+
++4.0 TBD
++ New API in support of GO closures.
++
+3.2.1 Nov-12-14
+ Build fix for non-iOS AArch64 targets.
+
@@ -14100,7 +14106,7 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/README modified/Modules/_ctypes/libffi
+libffi-discuss@sourceware.org.
diff -Nru orig/Modules/_ctypes/libffi_ios/README.python modified/Modules/_ctypes/libffi_ios/README.python
--- orig/Modules/_ctypes/libffi_ios/README.python 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/README.python 2015-04-26 09:00:07.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/README.python 2015-12-20 18:48:11.000000000 +0800
@@ -0,0 +1,14 @@
+This directory contains the generated source code for running libffi
+on iOS platforms (physical and simulator). It contains support for
@@ -14114,16003 +14120,8908 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/README.python modified/Modules/_ctypes
+generated code directories. It has been pruned of source files that are
+not needed for ctypes.
+
-+The code in this directory uses the source code from libffi 3.2.1, released
-+in November 2014.
-diff -Nru orig/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c modified/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c
---- orig/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,936 @@
-+#ifdef __arm__
-+
-+/* -----------------------------------------------------------------------
-+ ffi.c - Copyright (c) 2011 Timothy Wall
-+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
-+ Copyright (c) 2011 Anthony Green
-+ Copyright (c) 2011 Free Software Foundation
-+ Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
++The code in this directory uses the source code from a pre-release version
++and patched verion of libffi 4.
+diff -Nru orig/Modules/_ctypes/libffi_ios/aarch64/ffi_arm64.c modified/Modules/_ctypes/libffi_ios/aarch64/ffi_arm64.c
+--- orig/Modules/_ctypes/libffi_ios/aarch64/ffi_arm64.c 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/aarch64/ffi_arm64.c 2015-12-20 22:04:51.000000000 +0800
+@@ -0,0 +1,934 @@
++#ifdef __arm64__
+
-+ ARM Foreign Function Interface
++/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++Permission is hereby granted, free of charge, to any person obtaining
++a copy of this software and associated documentation files (the
++``Software''), to deal in the Software without restriction, including
++without limitation the rights to use, copy, modify, merge, publish,
++distribute, sublicense, and/or sell copies of the Software, and to
++permit persons to whom the Software is furnished to do so, subject to
++the following conditions:
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++The above copyright notice and this permission notice shall be
++included in all copies or substantial portions of the Software.
+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
++#include
++#include
++#include
++#include
+#include
+#include
++#include "internal.h"
+
-+#include
++/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
++ all further uses in this file will refer to the 128-bit type. */
++#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
++# if FFI_TYPE_LONGDOUBLE != 4
++# error FFI_TYPE_LONGDOUBLE out of date
++# endif
++#else
++# undef FFI_TYPE_LONGDOUBLE
++# define FFI_TYPE_LONGDOUBLE 4
++#endif
+
-+/* Forward declares. */
-+static int vfp_type_p (ffi_type *);
-+static void layout_vfp_args (ffi_cif *);
++union _d
++{
++ UINT64 d;
++ UINT32 s[2];
++};
+
-+int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space);
-+int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space);
++struct _v
++{
++ union _d d[2] __attribute__((aligned(16)));
++};
+
-+static char* ffi_align(ffi_type **p_arg, char *argp)
++struct call_context
+{
-+ /* Align if necessary */
-+ register size_t alignment = (*p_arg)->alignment;
-+ if (alignment < 4)
-+ {
-+ alignment = 4;
-+ }
-+#ifdef _WIN32_WCE
-+ if (alignment > 4)
-+ {
-+ alignment = 4;
-+ }
-+#endif
-+ if ((alignment - 1) & (unsigned) argp)
-+ {
-+ argp = (char *) ALIGN(argp, alignment);
-+ }
++ struct _v v[N_V_ARG_REG];
++ UINT64 x[N_X_ARG_REG];
++};
+
-+ if ((*p_arg)->type == FFI_TYPE_STRUCT)
-+ {
-+ argp = (char *) ALIGN(argp, 4);
-+ }
-+ return argp;
-+}
++#if defined (__clang__) && defined (__APPLE__)
++extern void sys_icache_invalidate (void *start, size_t len);
++#endif
+
-+static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack)
++static inline void
++ffi_clear_cache (void *start, void *end)
+{
-+ register char* argp = stack;
-+ register ffi_type **p_arg = arg_type;
-+ register void **p_argv = arg;
-+ register size_t z = (*p_arg)->size;
-+ if (z < sizeof(int))
-+ {
-+ z = sizeof(int);
-+ switch ((*p_arg)->type)
-+ {
-+ case FFI_TYPE_SINT8:
-+ *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_UINT8:
-+ *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_SINT16:
-+ *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_UINT16:
-+ *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_STRUCT:
-+ memcpy(argp, *p_argv, (*p_arg)->size);
-+ break;
-+
-+ default:
-+ FFI_ASSERT(0);
-+ }
-+ }
-+ else if (z == sizeof(int))
-+ {
-+ if ((*p_arg)->type == FFI_TYPE_FLOAT)
-+ *(float *) argp = *(float *)(* p_argv);
-+ else
-+ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
-+ }
-+ else if (z == sizeof(double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
-+ {
-+ *(double *) argp = *(double *)(* p_argv);
-+ }
-+ else
-+ {
-+ memcpy(argp, *p_argv, z);
-+ }
-+ return z;
++#if defined (__clang__) && defined (__APPLE__)
++ sys_icache_invalidate (start, (char *)end - (char *)start);
++#elif defined (__GNUC__)
++ __builtin___clear_cache (start, end);
++#else
++#error "Missing builtin to flush instruction cache"
++#endif
+}
-+/* ffi_prep_args is called by the assembly routine once stack space
-+ has been allocated for the function's arguments
-+
-+ The vfp_space parameter is the load area for VFP regs, the return
-+ value is cif->vfp_used (word bitset of VFP regs used for passing
-+ arguments). These are only used for the VFP hard-float ABI.
-+*/
-+int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space)
-+{
-+ register unsigned int i;
-+ register void **p_argv;
-+ register char *argp;
-+ register ffi_type **p_arg;
-+ argp = stack;
-+
+
-+ if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
-+ *(void **) argp = ecif->rvalue;
-+ argp += 4;
-+ }
++#if FFI_EXEC_TRAMPOLINE_TABLE
+
-+ p_argv = ecif->avalue;
++#ifdef __MACH__
++#include
++#endif
+
-+ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-+ (i != 0);
-+ i--, p_arg++, p_argv++)
-+ {
-+ argp = ffi_align(p_arg, argp);
-+ argp += ffi_put_arg(p_arg, p_argv, argp);
-+ }
++#endif
+
-+ return 0;
-+}
++/* A subroutine of is_vfp_type. Given a structure type, return the type code
++ of the first non-structure element. Recurse for structure elements.
++ Return -1 if the structure is in fact empty, i.e. no nested elements. */
+
-+int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
++static int
++is_hfa0 (const ffi_type *ty)
+{
-+ register unsigned int i, vi = 0;
-+ register void **p_argv;
-+ register char *argp, *regp, *eo_regp;
-+ register ffi_type **p_arg;
-+ char stack_used = 0;
-+ char done_with_regs = 0;
-+ char is_vfp_type;
++ ffi_type **elements = ty->elements;
++ int i, ret = -1;
+
-+ // make sure we are using FFI_VFP
-+ FFI_ASSERT(ecif->cif->abi == FFI_VFP);
++ if (elements != NULL)
++ for (i = 0; elements[i]; ++i)
++ {
++ ret = elements[i]->type;
++ if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
++ {
++ ret = is_hfa0 (elements[i]);
++ if (ret < 0)
++ continue;
++ }
++ break;
++ }
+
-+ /* the first 4 words on the stack are used for values passed in core
-+ * registers. */
-+ regp = stack;
-+ eo_regp = argp = regp + 16;
-+
++ return ret;
++}
+
-+ /* if the function returns an FFI_TYPE_STRUCT in memory, that address is
-+ * passed in r0 to the function */
-+ if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
-+ *(void **) regp = ecif->rvalue;
-+ regp += 4;
-+ }
++/* A subroutine of is_vfp_type. Given a structure type, return true if all
++ of the non-structure elements are the same as CANDIDATE. */
+
-+ p_argv = ecif->avalue;
++static int
++is_hfa1 (const ffi_type *ty, int candidate)
++{
++ ffi_type **elements = ty->elements;
++ int i;
+
-+ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
-+ (i != 0);
-+ i--, p_arg++, p_argv++)
-+ {
-+ is_vfp_type = vfp_type_p (*p_arg);
++ if (elements != NULL)
++ for (i = 0; elements[i]; ++i)
++ {
++ int t = elements[i]->type;
++ if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
++ {
++ if (!is_hfa1 (elements[i], candidate))
++ return 0;
++ }
++ else if (t != candidate)
++ return 0;
++ }
+
-+ /* Allocated in VFP registers. */
-+ if(vi < ecif->cif->vfp_nargs && is_vfp_type)
-+ {
-+ char *vfp_slot = (char *)(vfp_space + ecif->cif->vfp_args[vi++]);
-+ ffi_put_arg(p_arg, p_argv, vfp_slot);
-+ continue;
-+ }
-+ /* Try allocating in core registers. */
-+ else if (!done_with_regs && !is_vfp_type)
-+ {
-+ char *tregp = ffi_align(p_arg, regp);
-+ size_t size = (*p_arg)->size;
-+ size = (size < 4)? 4 : size; // pad
-+ /* Check if there is space left in the aligned register area to place
-+ * the argument */
-+ if(tregp + size <= eo_regp)
-+ {
-+ regp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
-+ done_with_regs = (regp == argp);
-+ // ensure we did not write into the stack area
-+ FFI_ASSERT(regp <= argp);
-+ continue;
-+ }
-+ /* In case there are no arguments in the stack area yet,
-+ the argument is passed in the remaining core registers and on the
-+ stack. */
-+ else if (!stack_used)
-+ {
-+ stack_used = 1;
-+ done_with_regs = 1;
-+ argp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
-+ FFI_ASSERT(eo_regp < argp);
-+ continue;
-+ }
-+ }
-+ /* Base case, arguments are passed on the stack */
-+ stack_used = 1;
-+ argp = ffi_align(p_arg, argp);
-+ argp += ffi_put_arg(p_arg, p_argv, argp);
-+ }
-+ /* Indicate the VFP registers used. */
-+ return ecif->cif->vfp_used;
++ return 1;
+}
+
-+/* Perform machine dependent cif processing */
-+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++/* Determine if TY may be allocated to the FP registers. This is both an
++ fp scalar type as well as an homogenous floating point aggregate (HFA).
++ That is, a structure consisting of 1 to 4 members of all the same type,
++ where that type is an fp scalar.
++
++ Returns non-zero iff TY is an HFA. The result is the AARCH64_RET_*
++ constant for the type. */
++
++static int
++is_vfp_type (const ffi_type *ty)
+{
-+ int type_code;
-+ /* Round the stack up to a multiple of 8 bytes. This isn't needed
-+ everywhere, but it is on some platforms, and it doesn't harm anything
-+ when it isn't needed. */
-+ cif->bytes = (cif->bytes + 7) & ~7;
++ ffi_type **elements;
++ int candidate, i;
++ size_t size, ele_count;
+
-+ /* Set the return type flag */
-+ switch (cif->rtype->type)
++ /* Quickest tests first. */
++ candidate = ty->type;
++ switch (candidate)
+ {
-+ case FFI_TYPE_VOID:
++ default:
++ return 0;
+ case FFI_TYPE_FLOAT:
+ case FFI_TYPE_DOUBLE:
-+ cif->flags = (unsigned) cif->rtype->type;
-+ break;
-+
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_UINT64:
-+ cif->flags = (unsigned) FFI_TYPE_SINT64;
-+ break;
-+
-+ case FFI_TYPE_STRUCT:
-+ if (cif->abi == FFI_VFP
-+ && (type_code = vfp_type_p (cif->rtype)) != 0)
++ case FFI_TYPE_LONGDOUBLE:
++ ele_count = 1;
++ goto done;
++ case FFI_TYPE_COMPLEX:
++ candidate = ty->elements[0]->type;
++ switch (candidate)
+ {
-+ /* A Composite Type passed in VFP registers, either
-+ FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
-+ cif->flags = (unsigned) type_code;
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ ele_count = 2;
++ goto done;
+ }
-+ else if (cif->rtype->size <= 4)
-+ /* A Composite Type not larger than 4 bytes is returned in r0. */
-+ cif->flags = (unsigned)FFI_TYPE_INT;
-+ else
-+ /* A Composite Type larger than 4 bytes, or whose size cannot
-+ be determined statically ... is stored in memory at an
-+ address passed [in r0]. */
-+ cif->flags = (unsigned)FFI_TYPE_STRUCT;
-+ break;
-+
-+ default:
-+ cif->flags = FFI_TYPE_INT;
++ return 0;
++ case FFI_TYPE_STRUCT:
+ break;
+ }
+
-+ /* Map out the register placements of VFP register args.
-+ The VFP hard-float calling conventions are slightly more sophisticated than
-+ the base calling conventions, so we do it here instead of in ffi_prep_args(). */
-+ if (cif->abi == FFI_VFP)
-+ layout_vfp_args (cif);
-+
-+ return FFI_OK;
-+}
-+
-+/* Perform machine dependent cif processing for variadic calls */
-+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs)
-+{
-+ /* VFP variadic calls actually use the SYSV ABI */
-+ if (cif->abi == FFI_VFP)
-+ cif->abi = FFI_SYSV;
-+
-+ return ffi_prep_cif_machdep(cif);
-+}
-+
-+/* Prototypes for assembly functions, in sysv.S */
-+extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
-+extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
-+
-+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
-+{
-+ extended_cif ecif;
-+
-+ int small_struct = (cif->flags == FFI_TYPE_INT
-+ && cif->rtype->type == FFI_TYPE_STRUCT);
-+ int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
-+ || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
-+
-+ unsigned int temp;
-+
-+ ecif.cif = cif;
-+ ecif.avalue = avalue;
-+
-+ /* If the return value is a struct and we don't have a return */
-+ /* value address then we need to make one */
++ /* No HFA types are smaller than 4 bytes, or larger than 64 bytes. */
++ size = ty->size;
++ if (size < 4 || size > 64)
++ return 0;
+
-+ if ((rvalue == NULL) &&
-+ (cif->flags == FFI_TYPE_STRUCT))
-+ {
-+ ecif.rvalue = alloca(cif->rtype->size);
-+ }
-+ else if (small_struct)
-+ ecif.rvalue = &temp;
-+ else if (vfp_struct)
++ /* Find the type of the first non-structure member. */
++ elements = ty->elements;
++ candidate = elements[0]->type;
++ if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
+ {
-+ /* Largest case is double x 4. */
-+ ecif.rvalue = alloca(32);
++ for (i = 0; ; ++i)
++ {
++ candidate = is_hfa0 (elements[i]);
++ if (candidate >= 0)
++ break;
++ }
+ }
-+ else
-+ ecif.rvalue = rvalue;
+
-+ switch (cif->abi)
++ /* If the first member is not a floating point type, it's not an HFA.
++ Also quickly re-check the size of the structure. */
++ switch (candidate)
+ {
-+ case FFI_SYSV:
-+ ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
++ case FFI_TYPE_FLOAT:
++ ele_count = size / sizeof(float);
++ if (size != ele_count * sizeof(float))
++ return 0;
+ break;
-+
-+ case FFI_VFP:
-+#ifdef __ARM_EABI__
-+ ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
++ case FFI_TYPE_DOUBLE:
++ ele_count = size / sizeof(double);
++ if (size != ele_count * sizeof(double))
++ return 0;
+ break;
-+#endif
-+
-+ default:
-+ FFI_ASSERT(0);
++ case FFI_TYPE_LONGDOUBLE:
++ ele_count = size / sizeof(long double);
++ if (size != ele_count * sizeof(long double))
++ return 0;
+ break;
++ default:
++ return 0;
+ }
-+ if (small_struct)
-+ {
-+ FFI_ASSERT(rvalue != NULL);
-+ memcpy (rvalue, &temp, cif->rtype->size);
-+ }
-+
-+ else if (vfp_struct)
++ if (ele_count > 4)
++ return 0;
++
++ /* Finally, make sure that all scalar elements are the same type. */
++ for (i = 0; elements[i]; ++i)
+ {
-+ FFI_ASSERT(rvalue != NULL);
-+ memcpy (rvalue, ecif.rvalue, cif->rtype->size);
++ int t = elements[i]->type;
++ if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
++ {
++ if (!is_hfa1 (elements[i], candidate))
++ return 0;
++ }
++ else if (t != candidate)
++ return 0;
+ }
-+
-+}
-+
-+/** private members **/
-+
-+static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-+ void** args, ffi_cif* cif, float *vfp_stack);
+
-+static void ffi_prep_incoming_args_VFP (char *stack, void **ret,
-+ void** args, ffi_cif* cif, float *vfp_stack);
-+
-+void ffi_closure_SYSV (ffi_closure *);
++ /* All tests succeeded. Encode the result. */
++ done:
++ return candidate * 4 + (4 - ele_count);
++}
+
-+void ffi_closure_VFP (ffi_closure *);
++/* Representation of the procedure call argument marshalling
++ state.
+
-+/* This function is jumped to by the trampoline */
++ The terse state variable names match the names used in the AARCH64
++ PCS. */
+
-+unsigned int FFI_HIDDEN
-+ffi_closure_inner (ffi_closure *closure,
-+ void **respp, void *args, void *vfp_args)
++struct arg_state
+{
-+ // our various things...
-+ ffi_cif *cif;
-+ void **arg_area;
-+
-+ cif = closure->cif;
-+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
-+
-+ /* this call will initialize ARG_AREA, such that each
-+ * element in that array points to the corresponding
-+ * value on the stack; and if the function returns
-+ * a structure, it will re-set RESP to point to the
-+ * structure return address. */
-+ if (cif->abi == FFI_VFP)
-+ ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args);
-+ else
-+ ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
++ unsigned ngrn; /* Next general-purpose register number. */
++ unsigned nsrn; /* Next vector register number. */
++ size_t nsaa; /* Next stack offset. */
+
-+ (closure->fun) (cif, *respp, arg_area, closure->user_data);
++#if defined (__APPLE__)
++ unsigned allocating_variadic;
++#endif
++};
+
-+ return cif->flags;
++/* Initialize a procedure call argument marshalling state. */
++static void
++arg_init (struct arg_state *state)
++{
++ state->ngrn = 0;
++ state->nsrn = 0;
++ state->nsaa = 0;
++#if defined (__APPLE__)
++ state->allocating_variadic = 0;
++#endif
+}
+
-+/*@-exportheader@*/
-+static void
-+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
-+ void **avalue, ffi_cif *cif,
-+ /* Used only under VFP hard-float ABI. */
-+ float *vfp_stack)
-+/*@=exportheader@*/
++/* Allocate an aligned slot on the stack and return a pointer to it. */
++static void *
++allocate_to_stack (struct arg_state *state, void *stack,
++ size_t alignment, size_t size)
+{
-+ register unsigned int i;
-+ register void **p_argv;
-+ register char *argp;
-+ register ffi_type **p_arg;
-+
-+ argp = stack;
-+
-+ if ( cif->flags == FFI_TYPE_STRUCT ) {
-+ *rvalue = *(void **) argp;
-+ argp += 4;
-+ }
-+
-+ p_argv = avalue;
-+
-+ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
-+ {
-+ size_t z;
-+
-+ argp = ffi_align(p_arg, argp);
-+
-+ z = (*p_arg)->size;
-+
-+ /* because we're little endian, this is what it turns into. */
++ size_t nsaa = state->nsaa;
+
-+ *p_argv = (void*) argp;
++ /* Round up the NSAA to the larger of 8 or the natural
++ alignment of the argument's type. */
++#if defined (__APPLE__)
++ if (state->allocating_variadic && alignment < 8)
++ alignment = 8;
++#else
++ if (alignment < 8)
++ alignment = 8;
++#endif
++
++ nsaa = ALIGN (nsaa, alignment);
++ state->nsaa = nsaa + size;
+
-+ p_argv++;
-+ argp += z;
-+ }
-+
-+ return;
++ return (char *)stack + nsaa;
+}
+
-+/*@-exportheader@*/
-+static void
-+ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
-+ void **avalue, ffi_cif *cif,
-+ /* Used only under VFP hard-float ABI. */
-+ float *vfp_stack)
-+/*@=exportheader@*/
++static ffi_arg
++extend_integer_type (void *source, int type)
+{
-+ register unsigned int i, vi = 0;
-+ register void **p_argv;
-+ register char *argp, *regp, *eo_regp;
-+ register ffi_type **p_arg;
-+ char done_with_regs = 0;
-+ char stack_used = 0;
-+ char is_vfp_type;
-+
-+ FFI_ASSERT(cif->abi == FFI_VFP);
-+ regp = stack;
-+ eo_regp = argp = regp + 16;
-+
-+ if ( cif->flags == FFI_TYPE_STRUCT ) {
-+ *rvalue = *(void **) regp;
-+ regp += 4;
-+ }
-+
-+ p_argv = avalue;
-+
-+ for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
++ switch (type)
+ {
-+ size_t z;
-+ is_vfp_type = vfp_type_p (*p_arg);
-+
-+ if(vi < cif->vfp_nargs && is_vfp_type)
-+ {
-+ *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
-+ continue;
-+ }
-+ else if (!done_with_regs && !is_vfp_type)
-+ {
-+ char* tregp = ffi_align(p_arg, regp);
-+
-+ z = (*p_arg)->size;
-+ z = (z < 4)? 4 : z; // pad
-+
-+ /* if the arguments either fits into the registers or uses registers
-+ * and stack, while we haven't read other things from the stack */
-+ if(tregp + z <= eo_regp || !stack_used)
-+ {
-+ /* because we're little endian, this is what it turns into. */
-+ *p_argv = (void*) tregp;
-+
-+ p_argv++;
-+ regp = tregp + z;
-+ // if we read past the last core register, make sure we have not read
-+ // from the stack before and continue reading after regp
-+ if(regp > eo_regp)
-+ {
-+ if(stack_used)
-+ {
-+ abort(); // we should never read past the end of the register
-+ // are if the stack is already in use
-+ }
-+ argp = regp;
-+ }
-+ if(regp >= eo_regp)
-+ {
-+ done_with_regs = 1;
-+ stack_used = 1;
-+ }
-+ continue;
-+ }
-+ }
-+ stack_used = 1;
-+
-+ argp = ffi_align(p_arg, argp);
-+
-+ z = (*p_arg)->size;
-+
-+ /* because we're little endian, this is what it turns into. */
-+
-+ *p_argv = (void*) argp;
-+
-+ p_argv++;
-+ argp += z;
++ case FFI_TYPE_UINT8:
++ return *(UINT8 *) source;
++ case FFI_TYPE_SINT8:
++ return *(SINT8 *) source;
++ case FFI_TYPE_UINT16:
++ return *(UINT16 *) source;
++ case FFI_TYPE_SINT16:
++ return *(SINT16 *) source;
++ case FFI_TYPE_UINT32:
++ return *(UINT32 *) source;
++ case FFI_TYPE_INT:
++ case FFI_TYPE_SINT32:
++ return *(SINT32 *) source;
++ case FFI_TYPE_UINT64:
++ case FFI_TYPE_SINT64:
++ return *(UINT64 *) source;
++ break;
++ case FFI_TYPE_POINTER:
++ return *(uintptr_t *) source;
++ default:
++ abort();
+ }
-+
-+ return;
+}
+
-+/* How to make a trampoline. */
-+
-+extern unsigned int ffi_arm_trampoline[3];
-+
-+#if FFI_EXEC_TRAMPOLINE_TABLE
-+
-+#include
-+#include
-+#include
-+#include
-+
-+extern void *ffi_closure_trampoline_table_page;
-+
-+typedef struct ffi_trampoline_table ffi_trampoline_table;
-+typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
-+
-+struct ffi_trampoline_table {
-+ /* contiguous writable and executable pages */
-+ vm_address_t config_page;
-+ vm_address_t trampoline_page;
-+
-+ /* free list tracking */
-+ uint16_t free_count;
-+ ffi_trampoline_table_entry *free_list;
-+ ffi_trampoline_table_entry *free_list_pool;
-+
-+ ffi_trampoline_table *prev;
-+ ffi_trampoline_table *next;
-+};
-+
-+struct ffi_trampoline_table_entry {
-+ void *(*trampoline)();
-+ ffi_trampoline_table_entry *next;
-+};
++static void
++extend_hfa_type (void *dest, void *src, int h)
++{
++ int f = h - AARCH64_RET_S4;
++ void *x0;
+
-+/* Override the standard architecture trampoline size */
-+// XXX TODO - Fix
-+#undef FFI_TRAMPOLINE_SIZE
-+#define FFI_TRAMPOLINE_SIZE 12
-+
-+/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
-+#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
-+
-+/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
-+#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
-+
-+/* Total number of trampolines that fit in one trampoline table */
-+#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
-+
-+static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
-+static ffi_trampoline_table *ffi_trampoline_tables = NULL;
++ asm volatile (
++ "adr %0, 0f\n"
++" add %0, %0, %1\n"
++" br %0\n"
++"0: ldp s16, s17, [%3]\n" /* S4 */
++" ldp s18, s19, [%3, #8]\n"
++" b 4f\n"
++" ldp s16, s17, [%3]\n" /* S3 */
++" ldr s18, [%3, #8]\n"
++" b 3f\n"
++" ldp s16, s17, [%3]\n" /* S2 */
++" b 2f\n"
++" nop\n"
++" ldr s16, [%3]\n" /* S1 */
++" b 1f\n"
++" nop\n"
++" ldp d16, d17, [%3]\n" /* D4 */
++" ldp d18, d19, [%3, #16]\n"
++" b 4f\n"
++" ldp d16, d17, [%3]\n" /* D3 */
++" ldr d18, [%3, #16]\n"
++" b 3f\n"
++" ldp d16, d17, [%3]\n" /* D2 */
++" b 2f\n"
++" nop\n"
++" ldr d16, [%3]\n" /* D1 */
++" b 1f\n"
++" nop\n"
++" ldp q16, q17, [%3]\n" /* Q4 */
++" ldp q18, q19, [%3, #16]\n"
++" b 4f\n"
++" ldp q16, q17, [%3]\n" /* Q3 */
++" ldr q18, [%3, #16]\n"
++" b 3f\n"
++" ldp q16, q17, [%3]\n" /* Q2 */
++" b 2f\n"
++" nop\n"
++" ldr q16, [%3]\n" /* Q1 */
++" b 1f\n"
++"4: str q19, [%2, #48]\n"
++"3: str q18, [%2, #32]\n"
++"2: str q17, [%2, #16]\n"
++"1: str q16, [%2]"
++ : "=&r"(x0)
++ : "r"(f * 12), "r"(dest), "r"(src)
++ : "memory", "v16", "v17", "v18", "v19");
++}
+
-+static ffi_trampoline_table *
-+ffi_trampoline_table_alloc ()
++static void *
++compress_hfa_type (void *dest, void *reg, int h)
+{
-+ ffi_trampoline_table *table = NULL;
-+
-+ /* Loop until we can allocate two contiguous pages */
-+ while (table == NULL) {
-+ vm_address_t config_page = 0x0;
-+ kern_return_t kt;
-+
-+ /* Try to allocate two pages */
-+ kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
-+ if (kt != KERN_SUCCESS) {
-+ fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
++ switch (h)
++ {
++ case AARCH64_RET_S1:
++ if (dest == reg)
++ {
++#ifdef __AARCH64EB__
++ dest += 12;
++#endif
++ }
++ else
++ *(float *)dest = *(float *)reg;
+ break;
-+ }
-+
-+ /* Now drop the second half of the allocation to make room for the trampoline table */
-+ vm_address_t trampoline_page = config_page+PAGE_SIZE;
-+ kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
-+ if (kt != KERN_SUCCESS) {
-+ fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
++ case AARCH64_RET_S2:
++ asm ("ldp q16, q17, [%1]\n\t"
++ "st2 { v16.s, v17.s }[0], [%0]"
++ : : "r"(dest), "r"(reg) : "memory", "v16", "v17");
++ break;
++ case AARCH64_RET_S3:
++ asm ("ldp q16, q17, [%1]\n\t"
++ "ldr q18, [%1, #32]\n\t"
++ "st3 { v16.s, v17.s, v18.s }[0], [%0]"
++ : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
++ break;
++ case AARCH64_RET_S4:
++ asm ("ldp q16, q17, [%1]\n\t"
++ "ldp q18, q19, [%1, #32]\n\t"
++ "st4 { v16.s, v17.s, v18.s, v19.s }[0], [%0]"
++ : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
+ break;
-+ }
-+
-+ /* Remap the trampoline table to directly follow the config page */
-+ vm_prot_t cur_prot;
-+ vm_prot_t max_prot;
-+
-+ kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
+
-+ /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
-+ if (kt != KERN_SUCCESS) {
-+ /* Log unexpected failures */
-+ if (kt != KERN_NO_SPACE) {
-+ fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
-+ }
++ case AARCH64_RET_D1:
++ if (dest == reg)
++ {
++#ifdef __AARCH64EB__
++ dest += 8;
++#endif
++ }
++ else
++ *(double *)dest = *(double *)reg;
++ break;
++ case AARCH64_RET_D2:
++ asm ("ldp q16, q17, [%1]\n\t"
++ "st2 { v16.d, v17.d }[0], [%0]"
++ : : "r"(dest), "r"(reg) : "memory", "v16", "v17");
++ break;
++ case AARCH64_RET_D3:
++ asm ("ldp q16, q17, [%1]\n\t"
++ "ldr q18, [%1, #32]\n\t"
++ "st3 { v16.d, v17.d, v18.d }[0], [%0]"
++ : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
++ break;
++ case AARCH64_RET_D4:
++ asm ("ldp q16, q17, [%1]\n\t"
++ "ldp q18, q19, [%1, #32]\n\t"
++ "st4 { v16.d, v17.d, v18.d, v19.d }[0], [%0]"
++ : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
++ break;
+
-+ vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
-+ continue;
++ default:
++ if (dest != reg)
++ return memcpy (dest, reg, 16 * (4 - (h & 3)));
++ break;
+ }
++ return dest;
++}
+
-+ /* We have valid trampoline and config pages */
-+ table = calloc (1, sizeof(ffi_trampoline_table));
-+ table->free_count = FFI_TRAMPOLINE_COUNT;
-+ table->config_page = config_page;
-+ table->trampoline_page = trampoline_page;
-+
-+ /* Create and initialize the free list */
-+ table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
-+
-+ uint16_t i;
-+ for (i = 0; i < table->free_count; i++) {
-+ ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
-+ entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
-+
-+ if (i < table->free_count - 1)
-+ entry->next = &table->free_list_pool[i+1];
-+ }
++/* Either allocate an appropriate register for the argument type, or if
++ none are available, allocate a stack slot and return a pointer
++ to the allocated space. */
+
-+ table->free_list = table->free_list_pool;
-+ }
++static void *
++allocate_int_to_reg_or_stack (struct call_context *context,
++ struct arg_state *state,
++ void *stack, size_t size)
++{
++ if (state->ngrn < N_X_ARG_REG)
++ return &context->x[state->ngrn++];
+
-+ return table;
++ state->ngrn = N_X_ARG_REG;
++ return allocate_to_stack (state, stack, size, size);
+}
+
-+void *
-+ffi_closure_alloc (size_t size, void **code)
++ffi_status
++ffi_prep_cif_machdep (ffi_cif *cif)
+{
-+ /* Create the closure */
-+ ffi_closure *closure = malloc(size);
-+ if (closure == NULL)
-+ return NULL;
-+
-+ pthread_mutex_lock(&ffi_trampoline_lock);
-+
-+ /* Check for an active trampoline table with available entries. */
-+ ffi_trampoline_table *table = ffi_trampoline_tables;
-+ if (table == NULL || table->free_list == NULL) {
-+ table = ffi_trampoline_table_alloc ();
-+ if (table == NULL) {
-+ free(closure);
-+ return NULL;
-+ }
++ ffi_type *rtype = cif->rtype;
++ size_t bytes = cif->bytes;
++ int flags, i, n;
+
-+ /* Insert the new table at the top of the list */
-+ table->next = ffi_trampoline_tables;
-+ if (table->next != NULL)
-+ table->next->prev = table;
++ switch (rtype->type)
++ {
++ case FFI_TYPE_VOID:
++ flags = AARCH64_RET_VOID;
++ break;
++ case FFI_TYPE_UINT8:
++ flags = AARCH64_RET_UINT8;
++ break;
++ case FFI_TYPE_UINT16:
++ flags = AARCH64_RET_UINT16;
++ break;
++ case FFI_TYPE_UINT32:
++ flags = AARCH64_RET_UINT32;
++ break;
++ case FFI_TYPE_SINT8:
++ flags = AARCH64_RET_SINT8;
++ break;
++ case FFI_TYPE_SINT16:
++ flags = AARCH64_RET_SINT16;
++ break;
++ case FFI_TYPE_INT:
++ case FFI_TYPE_SINT32:
++ flags = AARCH64_RET_SINT32;
++ break;
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_UINT64:
++ flags = AARCH64_RET_INT64;
++ break;
++ case FFI_TYPE_POINTER:
++ flags = (sizeof(void *) == 4 ? AARCH64_RET_UINT32 : AARCH64_RET_INT64);
++ break;
+
-+ ffi_trampoline_tables = table;
-+ }
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_COMPLEX:
++ flags = is_vfp_type (rtype);
++ if (flags == 0)
++ {
++ size_t s = rtype->size;
++ if (s > 16)
++ {
++ flags = AARCH64_RET_VOID | AARCH64_RET_IN_MEM;
++ bytes += 8;
++ }
++ else if (s == 16)
++ flags = AARCH64_RET_INT128;
++ else if (s == 8)
++ flags = AARCH64_RET_INT64;
++ else
++ flags = AARCH64_RET_INT128 | AARCH64_RET_NEED_COPY;
++ }
++ break;
+
-+ /* Claim the free entry */
-+ ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
-+ ffi_trampoline_tables->free_list = entry->next;
-+ ffi_trampoline_tables->free_count--;
-+ entry->next = NULL;
++ default:
++ abort();
++ }
+
-+ pthread_mutex_unlock(&ffi_trampoline_lock);
++ for (i = 0, n = cif->nargs; i < n; i++)
++ if (is_vfp_type (cif->arg_types[i]))
++ {
++ flags |= AARCH64_FLAG_ARG_V;
++ break;
++ }
+
-+ /* Initialize the return values */
-+ *code = entry->trampoline;
-+ closure->trampoline_table = table;
-+ closure->trampoline_table_entry = entry;
++ /* Round the stack up to a multiple of the stack alignment requirement. */
++ cif->bytes = ALIGN(bytes, 16);
++ cif->flags = flags;
++#if defined (__APPLE__)
++ cif->aarch64_nfixedargs = 0;
++#endif
+
-+ return closure;
++ return FFI_OK;
+}
+
-+void
-+ffi_closure_free (void *ptr)
++#if defined (__APPLE__)
++/* Perform Apple-specific cif processing for variadic calls */
++ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs)
+{
-+ ffi_closure *closure = ptr;
++ ffi_status status = ffi_prep_cif_machdep (cif);
++ cif->aarch64_nfixedargs = nfixedargs;
++ return status;
++}
++#endif /* __APPLE__ */
+
-+ pthread_mutex_lock(&ffi_trampoline_lock);
++extern void ffi_call_SYSV (struct call_context *context, void *frame,
++ void (*fn)(void), void *rvalue, int flags,
++ void *closure) FFI_HIDDEN;
+
-+ /* Fetch the table and entry references */
-+ ffi_trampoline_table *table = closure->trampoline_table;
-+ ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
++/* Call a function with the provided arguments and capture the return
++ value. */
++static void
++ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
++ void **avalue, void *closure)
++{
++ struct call_context *context;
++ void *stack, *frame, *rvalue;
++ struct arg_state state;
++ size_t stack_bytes, rtype_size, rsize;
++ int i, nargs, flags;
++ ffi_type *rtype;
+
-+ /* Return the entry to the free list */
-+ entry->next = table->free_list;
-+ table->free_list = entry;
-+ table->free_count++;
++ flags = cif->flags;
++ rtype = cif->rtype;
++ rtype_size = rtype->size;
++ stack_bytes = cif->bytes;
+
-+ /* If all trampolines within this table are free, and at least one other table exists, deallocate
-+ * the table */
-+ if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
-+ /* Remove from the list */
-+ if (table->prev != NULL)
-+ table->prev->next = table->next;
-+
-+ if (table->next != NULL)
-+ table->next->prev = table->prev;
-+
-+ /* Deallocate pages */
-+ kern_return_t kt;
-+ kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
-+ if (kt != KERN_SUCCESS)
-+ fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
-+
-+ kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
-+ if (kt != KERN_SUCCESS)
-+ fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
-+
-+ /* Deallocate free list */
-+ free (table->free_list_pool);
-+ free (table);
-+ } else if (ffi_trampoline_tables != table) {
-+ /* Otherwise, bump this table to the top of the list */
-+ table->prev = NULL;
-+ table->next = ffi_trampoline_tables;
-+ if (ffi_trampoline_tables != NULL)
-+ ffi_trampoline_tables->prev = table;
-+
-+ ffi_trampoline_tables = table;
-+ }
++ /* If the target function returns a structure via hidden pointer,
++ then we cannot allow a null rvalue. Otherwise, mash a null
++ rvalue to void return type. */
++ rsize = 0;
++ if (flags & AARCH64_RET_IN_MEM)
++ {
++ if (orig_rvalue == NULL)
++ rsize = rtype_size;
++ }
++ else if (orig_rvalue == NULL)
++ flags &= AARCH64_FLAG_ARG_V;
++ else if (flags & AARCH64_RET_NEED_COPY)
++ rsize = 16;
+
-+ pthread_mutex_unlock (&ffi_trampoline_lock);
++ /* Allocate consectutive stack for everything we'll need. */
++ context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize);
++ stack = context + 1;
++ frame = stack + stack_bytes;
++ rvalue = (rsize ? frame + 32 : orig_rvalue);
+
-+ /* Free the closure */
-+ free (closure);
-+}
++ arg_init (&state);
++ for (i = 0, nargs = cif->nargs; i < nargs; i++)
++ {
++ ffi_type *ty = cif->arg_types[i];
++ size_t s = ty->size;
++ void *a = avalue[i];
++ int h, t;
++
++ t = ty->type;
++ switch (t)
++ {
++ case FFI_TYPE_VOID:
++ FFI_ASSERT (0);
++ break;
+
++ /* If the argument is a basic type the argument is allocated to an
++ appropriate register, or if none are available, to the stack. */
++ case FFI_TYPE_INT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT16:
++ case FFI_TYPE_UINT32:
++ case FFI_TYPE_SINT32:
++ case FFI_TYPE_UINT64:
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_POINTER:
++ do_pointer:
++ {
++ ffi_arg ext = extend_integer_type (a, t);
++ if (state.ngrn < N_X_ARG_REG)
++ context->x[state.ngrn++] = ext;
++ else
++ {
++ void *d = allocate_to_stack (&state, stack, ty->alignment, s);
++ state.ngrn = N_X_ARG_REG;
++ /* Note that the default abi extends each argument
++ to a full 64-bit slot, while the iOS abi allocates
++ only enough space. */
++#ifdef __APPLE__
++ memcpy(d, a, s);
+#else
++ *(ffi_arg *)d = ext;
++#endif
++ }
++ }
++ break;
++
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_COMPLEX:
++ {
++ void *dest;
++
++ h = is_vfp_type (ty);
++ if (h)
++ {
++ int elems = 4 - (h & 3);
++ if (state.nsrn + elems <= N_V_ARG_REG)
++ {
++ dest = &context->v[state.nsrn];
++ state.nsrn += elems;
++ extend_hfa_type (dest, a, h);
++ break;
++ }
++ state.nsrn = N_V_ARG_REG;
++ dest = allocate_to_stack (&state, stack, ty->alignment, s);
++ }
++ else if (s > 16)
++ {
++ /* If the argument is a composite type that is larger than 16
++ bytes, then the argument has been copied to memory, and
++ the argument is replaced by a pointer to the copy. */
++ a = &avalue[i];
++ t = FFI_TYPE_POINTER;
++ goto do_pointer;
++ }
++ else
++ {
++ size_t n = (s + 7) / 8;
++ if (state.ngrn + n <= N_X_ARG_REG)
++ {
++ /* If the argument is a composite type and the size in
++ double-words is not more than the number of available
++ X registers, then the argument is copied into
++ consecutive X registers. */
++ dest = &context->x[state.ngrn];
++ state.ngrn += n;
++ }
++ else
++ {
++ /* Otherwise, there are insufficient X registers. Further
++ X register allocations are prevented, the NSAA is
++ adjusted and the argument is copied to memory at the
++ adjusted NSAA. */
++ state.ngrn = N_X_ARG_REG;
++ dest = allocate_to_stack (&state, stack, ty->alignment, s);
++ }
++ }
++ memcpy (dest, a, s);
++ }
++ break;
+
-+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
-+({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-+ unsigned int __fun = (unsigned int)(FUN); \
-+ unsigned int __ctx = (unsigned int)(CTX); \
-+ unsigned char *insns = (unsigned char *)(CTX); \
-+ memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline); \
-+ *(unsigned int*) &__tramp[12] = __ctx; \
-+ *(unsigned int*) &__tramp[16] = __fun; \
-+ __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \
-+ __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \
-+ /* Clear instruction \
-+ mapping. */ \
-+ })
++ default:
++ abort();
++ }
+
++#if defined (__APPLE__)
++ if (i + 1 == cif->aarch64_nfixedargs)
++ {
++ state.ngrn = N_X_ARG_REG;
++ state.nsrn = N_V_ARG_REG;
++ state.allocating_variadic = 1;
++ }
+#endif
++ }
+
-+/* the cif must already be prep'ed */
++ ffi_call_SYSV (context, frame, fn, rvalue, flags, closure);
++
++ if (flags & AARCH64_RET_NEED_COPY)
++ memcpy (orig_rvalue, rvalue, rtype_size);
++}
++
++void
++ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
++{
++ ffi_call_int (cif, fn, rvalue, avalue, NULL);
++}
++
++#ifdef FFI_GO_CLOSURES
++void
++ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
++ void **avalue, void *closure)
++{
++ ffi_call_int (cif, fn, rvalue, avalue, closure);
++}
++#endif /* FFI_GO_CLOSURES */
++
++/* Build a trampoline. */
++
++extern void ffi_closure_SYSV (void) FFI_HIDDEN;
++extern void ffi_closure_SYSV_V (void) FFI_HIDDEN;
+
+ffi_status
-+ffi_prep_closure_loc (ffi_closure* closure,
-+ ffi_cif* cif,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data,
-+ void *codeloc)
++ffi_prep_closure_loc (ffi_closure *closure,
++ ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data,
++ void *codeloc)
+{
-+ void (*closure_func)(ffi_closure*) = NULL;
++ if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
+
-+ if (cif->abi == FFI_SYSV)
-+ closure_func = &ffi_closure_SYSV;
-+#ifdef __ARM_EABI__
-+ else if (cif->abi == FFI_VFP)
-+ closure_func = &ffi_closure_VFP;
-+#endif
++ void (*start)(void);
++
++ if (cif->flags & AARCH64_FLAG_ARG_V)
++ start = ffi_closure_SYSV_V;
+ else
-+ return FFI_BAD_ABI;
++ start = ffi_closure_SYSV;
+
+#if FFI_EXEC_TRAMPOLINE_TABLE
-+ void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
++#ifdef __MACH__
++ void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
+ config[0] = closure;
-+ config[1] = closure_func;
++ config[1] = start;
++#endif
+#else
-+ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
-+ closure_func, \
-+ codeloc);
++ static const unsigned char trampoline[16] = {
++ 0x90, 0x00, 0x00, 0x58, /* ldr x16, tramp+16 */
++ 0xf1, 0xff, 0xff, 0x10, /* adr x17, tramp+0 */
++ 0x00, 0x02, 0x1f, 0xd6 /* br x16 */
++ };
++ char *tramp = closure->tramp;
++
++ memcpy (tramp, trampoline, sizeof(trampoline));
++
++ *(UINT64 *)(tramp + 16) = (uintptr_t)start;
++
++ ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
+#endif
+
-+ closure->cif = cif;
++ closure->cif = cif;
++ closure->fun = fun;
+ closure->user_data = user_data;
-+ closure->fun = fun;
+
+ return FFI_OK;
+}
+
-+/* Below are routines for VFP hard-float support. */
++#ifdef FFI_GO_CLOSURES
++extern void ffi_go_closure_SYSV (void) FFI_HIDDEN;
++extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN;
+
-+static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
++ffi_status
++ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif,
++ void (*fun)(ffi_cif*,void*,void**,void*))
+{
-+ switch (t->type)
-+ {
-+ case FFI_TYPE_FLOAT:
-+ case FFI_TYPE_DOUBLE:
-+ *elt = (int) t->type;
-+ *elnum = 1;
-+ return 1;
++ void (*start)(void);
+
-+ case FFI_TYPE_STRUCT_VFP_FLOAT:
-+ *elt = FFI_TYPE_FLOAT;
-+ *elnum = t->size / sizeof (float);
-+ return 1;
++ if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
+
-+ case FFI_TYPE_STRUCT_VFP_DOUBLE:
-+ *elt = FFI_TYPE_DOUBLE;
-+ *elnum = t->size / sizeof (double);
-+ return 1;
++ if (cif->flags & AARCH64_FLAG_ARG_V)
++ start = ffi_go_closure_SYSV_V;
++ else
++ start = ffi_go_closure_SYSV;
+
-+ case FFI_TYPE_STRUCT:;
-+ {
-+ int base_elt = 0, total_elnum = 0;
-+ ffi_type **el = t->elements;
-+ while (*el)
-+ {
-+ int el_elt = 0, el_elnum = 0;
-+ if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
-+ || (base_elt && base_elt != el_elt)
-+ || total_elnum + el_elnum > 4)
-+ return 0;
-+ base_elt = el_elt;
-+ total_elnum += el_elnum;
-+ el++;
-+ }
-+ *elnum = total_elnum;
-+ *elt = base_elt;
-+ return 1;
-+ }
-+ default: ;
-+ }
-+ return 0;
-+}
++ closure->tramp = start;
++ closure->cif = cif;
++ closure->fun = fun;
+
-+static int vfp_type_p (ffi_type *t)
-+{
-+ int elt, elnum;
-+ if (rec_vfp_type_p (t, &elt, &elnum))
-+ {
-+ if (t->type == FFI_TYPE_STRUCT)
-+ {
-+ if (elnum == 1)
-+ t->type = elt;
-+ else
-+ t->type = (elt == FFI_TYPE_FLOAT
-+ ? FFI_TYPE_STRUCT_VFP_FLOAT
-+ : FFI_TYPE_STRUCT_VFP_DOUBLE);
-+ }
-+ return (int) t->type;
-+ }
-+ return 0;
++ return FFI_OK;
+}
++#endif /* FFI_GO_CLOSURES */
++
++/* Primary handler to setup and invoke a function within a closure.
++
++ A closure when invoked enters via the assembler wrapper
++ ffi_closure_SYSV(). The wrapper allocates a call context on the
++ stack, saves the interesting registers (from the perspective of
++ the calling convention) into the context then passes control to
++ ffi_closure_SYSV_inner() passing the saved context and a pointer to
++ the stack at the point ffi_closure_SYSV() was invoked.
++
++ On the return path the assembler wrapper will reload call context
++ registers.
++
++ ffi_closure_SYSV_inner() marshalls the call context into ffi value
++ descriptors, invokes the wrapped function, then marshalls the return
++ value back into the call context. */
+
-+static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
++int FFI_HIDDEN
++ffi_closure_SYSV_inner (ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data,
++ struct call_context *context,
++ void *stack, void *rvalue, void *struct_rvalue)
+{
-+ short reg = cif->vfp_reg_free;
-+ int nregs = t->size / sizeof (float);
-+ int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
-+ || t->type == FFI_TYPE_FLOAT) ? 1 : 2);
-+ /* Align register number. */
-+ if ((reg & 1) && align == 2)
-+ reg++;
-+ while (reg + nregs <= 16)
++ void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
++ int i, h, nargs, flags;
++ struct arg_state state;
++
++ arg_init (&state);
++
++ for (i = 0, nargs = cif->nargs; i < nargs; i++)
+ {
-+ int s, new_used = 0;
-+ for (s = reg; s < reg + nregs; s++)
++ ffi_type *ty = cif->arg_types[i];
++ int t = ty->type;
++ size_t n, s = ty->size;
++
++ switch (t)
+ {
-+ new_used |= (1 << s);
-+ if (cif->vfp_used & (1 << s))
++ case FFI_TYPE_VOID:
++ FFI_ASSERT (0);
++ break;
++
++ case FFI_TYPE_INT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT16:
++ case FFI_TYPE_UINT32:
++ case FFI_TYPE_SINT32:
++ case FFI_TYPE_UINT64:
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_POINTER:
++ avalue[i] = allocate_int_to_reg_or_stack (context, &state, stack, s);
++ break;
++
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ case FFI_TYPE_LONGDOUBLE:
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_COMPLEX:
++ h = is_vfp_type (ty);
++ if (h)
+ {
-+ reg += align;
-+ goto next_reg;
++ n = 4 - (h & 3);
++ if (state.nsrn + n <= N_V_ARG_REG)
++ {
++ void *reg = &context->v[state.nsrn];
++ state.nsrn += n;
++
++ /* Eeek! We need a pointer to the structure, however the
++ homogeneous float elements are being passed in individual
++ registers, therefore for float and double the structure
++ is not represented as a contiguous sequence of bytes in
++ our saved register context. We don't need the original
++ contents of the register storage, so we reformat the
++ structure into the same memory. */
++ avalue[i] = compress_hfa_type (reg, reg, h);
++ }
++ else
++ {
++ state.nsrn = N_V_ARG_REG;
++ avalue[i] = allocate_to_stack (&state, stack,
++ ty->alignment, s);
++ }
+ }
-+ }
-+ /* Found regs to allocate. */
-+ cif->vfp_used |= new_used;
-+ cif->vfp_args[cif->vfp_nargs++] = reg;
++ else if (s > 16)
++ {
++ /* Replace Composite type of size greater than 16 with a
++ pointer. */
++ avalue[i] = *(void **)
++ allocate_int_to_reg_or_stack (context, &state, stack,
++ sizeof (void *));
++ }
++ else
++ {
++ n = (s + 7) / 8;
++ if (state.ngrn + n <= N_X_ARG_REG)
++ {
++ avalue[i] = &context->x[state.ngrn];
++ state.ngrn += n;
++ }
++ else
++ {
++ state.ngrn = N_X_ARG_REG;
++ avalue[i] = allocate_to_stack (&state, stack,
++ ty->alignment, s);
++ }
++ }
++ break;
+
-+ /* Update vfp_reg_free. */
-+ if (cif->vfp_used & (1 << cif->vfp_reg_free))
-+ {
-+ reg += nregs;
-+ while (cif->vfp_used & (1 << reg))
-+ reg += 1;
-+ cif->vfp_reg_free = reg;
++ default:
++ abort();
+ }
-+ return 0;
-+ next_reg: ;
+ }
-+ // done, mark all regs as used
-+ cif->vfp_reg_free = 16;
-+ cif->vfp_used = 0xFFFF;
-+ return 1;
-+}
+
-+static void layout_vfp_args (ffi_cif *cif)
-+{
-+ int i;
-+ /* Init VFP fields */
-+ cif->vfp_used = 0;
-+ cif->vfp_nargs = 0;
-+ cif->vfp_reg_free = 0;
-+ memset (cif->vfp_args, -1, 16); /* Init to -1. */
++ flags = cif->flags;
++ if (flags & AARCH64_RET_IN_MEM)
++ rvalue = struct_rvalue;
+
-+ for (i = 0; i < cif->nargs; i++)
-+ {
-+ ffi_type *t = cif->arg_types[i];
-+ if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1)
-+ {
-+ break;
-+ }
-+ }
++ fun (cif, rvalue, avalue, user_data);
++
++ return flags;
+}
+
+
+#endif
\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S modified/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S
---- orig/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,496 @@
-+#ifdef __arm__
+diff -Nru orig/Modules/_ctypes/libffi_ios/aarch64/internal.h modified/Modules/_ctypes/libffi_ios/aarch64/internal.h
+--- orig/Modules/_ctypes/libffi_ios/aarch64/internal.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/aarch64/internal.h 2015-12-20 19:03:29.000000000 +0800
+@@ -0,0 +1,67 @@
++/*
++Permission is hereby granted, free of charge, to any person obtaining
++a copy of this software and associated documentation files (the
++``Software''), to deal in the Software without restriction, including
++without limitation the rights to use, copy, modify, merge, publish,
++distribute, sublicense, and/or sell copies of the Software, and to
++permit persons to whom the Software is furnished to do so, subject to
++the following conditions:
+
-+/* -----------------------------------------------------------------------
-+ sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
-+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
-+
-+ ARM Foreign Function Interface
++The above copyright notice and this permission notice shall be
++included in all copies or substantial portions of the Software.
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++#define AARCH64_RET_VOID 0
++#define AARCH64_RET_INT64 1
++#define AARCH64_RET_INT128 2
+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
++#define AARCH64_RET_UNUSED3 3
++#define AARCH64_RET_UNUSED4 4
++#define AARCH64_RET_UNUSED5 5
++#define AARCH64_RET_UNUSED6 6
++#define AARCH64_RET_UNUSED7 7
+
-+#define LIBFFI_ASM
-+#include
-+#include
-+#ifdef HAVE_MACHINE_ASM_H
-+#include
-+#else
-+#ifdef __USER_LABEL_PREFIX__
-+#define CONCAT1(a, b) CONCAT2(a, b)
-+#define CONCAT2(a, b) a ## b
++/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4,
++ so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */
++#define AARCH64_RET_S4 8
++#define AARCH64_RET_S3 9
++#define AARCH64_RET_S2 10
++#define AARCH64_RET_S1 11
+
-+/* Use the right prefix for global labels. */
-+#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-+#else
-+#define CNAME(x) x
-+#endif
-+#ifdef __APPLE__
-+#define ENTRY(x) .globl _##x; _##x:
-+#else
-+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
-+#endif /* __APPLE__ */
-+#endif
++#define AARCH64_RET_D4 12
++#define AARCH64_RET_D3 13
++#define AARCH64_RET_D2 14
++#define AARCH64_RET_D1 15
+
-+#ifdef __ELF__
-+#define LSYM(x) .x
-+#else
-+#define LSYM(x) x
-+#endif
++#define AARCH64_RET_Q4 16
++#define AARCH64_RET_Q3 17
++#define AARCH64_RET_Q2 18
++#define AARCH64_RET_Q1 19
+
-+/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
-+ Function Call Guide */
-+#ifdef __APPLE__
-+#define __SOFTFP__
-+#endif
++/* Note that each of the sub-64-bit integers gets two entries. */
++#define AARCH64_RET_UINT8 20
++#define AARCH64_RET_UINT16 22
++#define AARCH64_RET_UINT32 24
+
-+/* We need a better way of testing for this, but for now, this is all
-+ we can do. */
-+@ This selects the minimum architecture level required.
-+#define __ARM_ARCH__ 3
++#define AARCH64_RET_SINT8 26
++#define AARCH64_RET_SINT16 28
++#define AARCH64_RET_SINT32 30
+
-+#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
-+# undef __ARM_ARCH__
-+# define __ARM_ARCH__ 4
-+#endif
-+
-+#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
-+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
-+ || defined(__ARM_ARCH_5TEJ__)
-+# undef __ARM_ARCH__
-+# define __ARM_ARCH__ 5
-+#endif
-+
-+#if 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(__ARM_ARCH_6M__)
-+# undef __ARM_ARCH__
-+# define __ARM_ARCH__ 6
-+#endif
-+
-+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
-+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
-+ || defined(__ARM_ARCH_7EM__)
-+# undef __ARM_ARCH__
-+# define __ARM_ARCH__ 7
-+#endif
-+
-+#if __ARM_ARCH__ >= 5
-+# define call_reg(x) blx x
-+#elif defined (__ARM_ARCH_4T__)
-+# define call_reg(x) mov lr, pc ; bx x
-+# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
-+# define __INTERWORKING__
-+# endif
-+#else
-+# define call_reg(x) mov lr, pc ; mov pc, x
-+#endif
-+
-+/* Conditionally compile unwinder directives. */
-+#ifdef __ARM_EABI__
-+#define UNWIND
-+#else
-+#define UNWIND @
-+#endif
-+
-+.syntax unified
-+
-+#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
-+#define ARM_FUNC_START(name) \
-+ .text; \
-+ .align 2; \
-+ .thumb; \
-+ .thumb_func; \
-+ ENTRY(name); \
-+ bx pc; \
-+ nop; \
-+ .arm; \
-+ UNWIND .fnstart; \
-+_L__##name:
-+#else
-+#define ARM_FUNC_START(name) \
-+ .text; \
-+ .align 2; \
-+ .arm; \
-+ ENTRY(name); \
-+ UNWIND .fnstart
-+#endif
-+
-+.macro RETLDM regs=, cond=, dirn=ia
-+#if defined (__INTERWORKING__)
-+ .ifc "\regs",""
-+ ldr\cond lr, [sp], #4
-+ .else
-+ ldm\cond\dirn sp!, {\regs, lr}
-+ .endif
-+ bx\cond lr
-+#else
-+ .ifc "\regs",""
-+ ldr\cond pc, [sp], #4
-+ .else
-+ ldm\cond\dirn sp!, {\regs, pc}
-+ .endif
-+#endif
-+.endm
-+
-+ @ r0: ffi_prep_args
-+ @ r1: &ecif
-+ @ r2: cif->bytes
-+ @ r3: fig->flags
-+ @ sp+0: ecif.rvalue
-+
-+ @ This assumes we are using gas.
-+ARM_FUNC_START(ffi_call_SYSV)
-+ @ Save registers
-+ stmfd sp!, {r0-r3, fp, lr}
-+ UNWIND .save {r0-r3, fp, lr}
-+ mov fp, sp
-+
-+ UNWIND .setfp fp, sp
-+
-+ @ Make room for all of the new args.
-+ sub sp, fp, r2
-+
-+ @ Place all of the ffi_prep_args in position
-+ mov r0, sp
-+ @ r1 already set
-+
-+ @ Call ffi_prep_args(stack, &ecif)
-+ bl CNAME(ffi_prep_args_SYSV)
-+
-+ @ move first 4 parameters in registers
-+ ldmia sp, {r0-r3}
-+
-+ @ and adjust stack
-+ sub lr, fp, sp @ cif->bytes == fp - sp
-+ ldr ip, [fp] @ load fn() in advance
-+ cmp lr, #16
-+ movhs lr, #16
-+ add sp, sp, lr
++#define AARCH64_RET_MASK 31
+
-+ @ call (fn) (...)
-+ call_reg(ip)
-+
-+ @ Remove the space we pushed for the args
-+ mov sp, fp
++#define AARCH64_RET_IN_MEM (1 << 5)
++#define AARCH64_RET_NEED_COPY (1 << 6)
+
-+ @ Load r2 with the pointer to storage for the return value
-+ ldr r2, [sp, #24]
++#define AARCH64_FLAG_ARG_V_BIT 7
++#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT)
+
-+ @ Load r3 with the return type code
-+ ldr r3, [sp, #12]
++#define N_X_ARG_REG 8
++#define N_V_ARG_REG 8
++#define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8)
+diff -Nru orig/Modules/_ctypes/libffi_ios/aarch64/sysv_arm64.S modified/Modules/_ctypes/libffi_ios/aarch64/sysv_arm64.S
+--- orig/Modules/_ctypes/libffi_ios/aarch64/sysv_arm64.S 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/aarch64/sysv_arm64.S 2015-12-20 22:31:37.000000000 +0800
+@@ -0,0 +1,443 @@
++#ifdef __arm64__
+
-+ @ If the return value pointer is NULL, assume no return value.
-+ cmp r2, #0
-+ beq LSYM(Lepilogue)
++/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
+
-+@ return INT
-+ cmp r3, #FFI_TYPE_INT
-+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-+ cmpne r3, #FFI_TYPE_FLOAT
-+#endif
-+ streq r0, [r2]
-+ beq LSYM(Lepilogue)
++Permission is hereby granted, free of charge, to any person obtaining
++a copy of this software and associated documentation files (the
++``Software''), to deal in the Software without restriction, including
++without limitation the rights to use, copy, modify, merge, publish,
++distribute, sublicense, and/or sell copies of the Software, and to
++permit persons to whom the Software is furnished to do so, subject to
++the following conditions:
+
-+ @ return INT64
-+ cmp r3, #FFI_TYPE_SINT64
-+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-+ cmpne r3, #FFI_TYPE_DOUBLE
-+#endif
-+ stmiaeq r2, {r0, r1}
++The above copyright notice and this permission notice shall be
++included in all copies or substantial portions of the Software.
+
-+#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
-+ beq LSYM(Lepilogue)
++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
++CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
-+@ return FLOAT
-+ cmp r3, #FFI_TYPE_FLOAT
-+ stfeqs f0, [r2]
-+ beq LSYM(Lepilogue)
++#define LIBFFI_ASM
++#include
++#include
++#include
++#include "internal.h"
+
-+@ return DOUBLE or LONGDOUBLE
-+ cmp r3, #FFI_TYPE_DOUBLE
-+ stfeqd f0, [r2]
-+#endif
++#ifdef HAVE_MACHINE_ASM_H
++#include
++#else
++#ifdef __USER_LABEL_PREFIX__
++#define CONCAT1(a, b) CONCAT2(a, b)
++#define CONCAT2(a, b) a ## b
+
-+LSYM(Lepilogue):
-+#if defined (__INTERWORKING__)
-+ ldmia sp!, {r0-r3,fp, lr}
-+ bx lr
++/* Use the right prefix for global labels. */
++#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
-+ ldmia sp!, {r0-r3,fp, pc}
++#define CNAME(x) x
+#endif
-+
-+.ffi_call_SYSV_end:
-+ UNWIND .fnend
-+#ifdef __ELF__
-+ .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+#endif
+
-+
-+/*
-+ unsigned int FFI_HIDDEN
-+ ffi_closure_inner (closure, respp, args)
-+ ffi_closure *closure;
-+ void **respp;
-+ void *args;
-+*/
-+
-+ARM_FUNC_START(ffi_closure_SYSV)
-+ UNWIND .pad #16
-+ add ip, sp, #16
-+ stmfd sp!, {ip, lr}
-+ UNWIND .save {r0, lr}
-+ add r2, sp, #8
-+ UNWIND .pad #16
-+ sub sp, sp, #16
-+ str sp, [sp, #8]
-+ add r1, sp, #8
-+ bl CNAME(ffi_closure_inner)
-+ cmp r0, #FFI_TYPE_INT
-+ beq .Lretint
-+
-+ cmp r0, #FFI_TYPE_FLOAT
-+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-+ beq .Lretint
++#ifdef __AARCH64EB__
++# define BE(X) X
+#else
-+ beq .Lretfloat
++# define BE(X) 0
+#endif
+
-+ cmp r0, #FFI_TYPE_DOUBLE
-+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-+ beq .Lretlonglong
++#ifdef __ILP32__
++#define PTR_REG(n) w##n
+#else
-+ beq .Lretdouble
++#define PTR_REG(n) x##n
+#endif
+
-+ cmp r0, #FFI_TYPE_LONGDOUBLE
-+#if defined(__SOFTFP__) || defined(__ARM_EABI__)
-+ beq .Lretlonglong
++#ifdef __ILP32__
++#define PTR_SIZE 4
+#else
-+ beq .Lretlongdouble
-+#endif
-+
-+ cmp r0, #FFI_TYPE_SINT64
-+ beq .Lretlonglong
-+.Lclosure_epilogue:
-+ add sp, sp, #16
-+ ldmfd sp, {sp, pc}
-+.Lretint:
-+ ldr r0, [sp]
-+ b .Lclosure_epilogue
-+.Lretlonglong:
-+ ldr r0, [sp]
-+ ldr r1, [sp, #4]
-+ b .Lclosure_epilogue
-+
-+#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
-+.Lretfloat:
-+ ldfs f0, [sp]
-+ b .Lclosure_epilogue
-+.Lretdouble:
-+ ldfd f0, [sp]
-+ b .Lclosure_epilogue
-+.Lretlongdouble:
-+ ldfd f0, [sp]
-+ b .Lclosure_epilogue
-+#endif
-+
-+.ffi_closure_SYSV_end:
-+ UNWIND .fnend
-+#ifdef __ELF__
-+ .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
++#define PTR_SIZE 8
+#endif
+
++ .text
++ .align 4
+
-+/* Below are VFP hard-float ABI call and closure implementations.
-+ Add VFP FPU directive here. This is only compiled into the library
-+ under EABI. */
-+#ifdef __ARM_EABI__
-+ .fpu vfp
-+
-+ @ r0: fn
-+ @ r1: &ecif
-+ @ r2: cif->bytes
-+ @ r3: fig->flags
-+ @ sp+0: ecif.rvalue
-+
-+ARM_FUNC_START(ffi_call_VFP)
-+ @ Save registers
-+ stmfd sp!, {r0-r3, fp, lr}
-+ UNWIND .save {r0-r3, fp, lr}
-+ mov fp, sp
-+ UNWIND .setfp fp, sp
-+
-+ @ Make room for all of the new args.
-+ sub sp, sp, r2
-+
-+ @ Make room for loading VFP args
-+ sub sp, sp, #64
-+
-+ @ Place all of the ffi_prep_args in position
-+ mov r0, sp
-+ @ r1 already set
-+ sub r2, fp, #64 @ VFP scratch space
-+
-+ @ Call ffi_prep_args(stack, &ecif, vfp_space)
-+ bl CNAME(ffi_prep_args_VFP)
-+
-+ @ Load VFP register args if needed
-+ cmp r0, #0
-+ mov ip, fp
-+ beq LSYM(Lbase_args)
-+
-+ @ Load only d0 if possible
-+ cmp r0, #3
-+ sub ip, fp, #64
-+ flddle d0, [ip]
-+ fldmiadgt ip, {d0-d7}
-+
-+LSYM(Lbase_args):
-+ @ move first 4 parameters in registers
-+ ldmia sp, {r0-r3}
-+
-+ @ and adjust stack
-+ sub lr, ip, sp @ cif->bytes == (fp - 64) - sp
-+ ldr ip, [fp] @ load fn() in advance
-+ cmp lr, #16
-+ movhs lr, #16
-+ add sp, sp, lr
-+
-+ @ call (fn) (...)
-+ call_reg(ip)
-+
-+ @ Remove the space we pushed for the args
-+ mov sp, fp
-+
-+ @ Load r2 with the pointer to storage for
-+ @ the return value
-+ ldr r2, [sp, #24]
++/* ffi_call_SYSV
++ extern void ffi_call_SYSV (void *stack, void *frame,
++ void (*fn)(void), void *rvalue,
++ int flags, void *closure);
+
-+ @ Load r3 with the return type code
-+ ldr r3, [sp, #12]
++ Therefore on entry we have:
+
-+ @ If the return value pointer is NULL,
-+ @ assume no return value.
-+ cmp r2, #0
-+ beq LSYM(Lepilogue_vfp)
++ x0 stack
++ x1 frame
++ x2 fn
++ x3 rvalue
++ x4 flags
++ x5 closure
++*/
+
-+ cmp r3, #FFI_TYPE_INT
-+ streq r0, [r2]
-+ beq LSYM(Lepilogue_vfp)
++ cfi_startproc
++CNAME(ffi_call_SYSV):
++ /* Use a stack frame allocated by our caller. */
++ cfi_def_cfa(x1, 32);
++ stp x29, x30, [x1]
++ mov x29, x1
++ mov sp, x0
++ cfi_def_cfa_register(x29)
++ cfi_rel_offset (x29, 0)
++ cfi_rel_offset (x30, 8)
+
-+ cmp r3, #FFI_TYPE_SINT64
-+ stmeqia r2, {r0, r1}
-+ beq LSYM(Lepilogue_vfp)
++ mov x9, x2 /* save fn */
++ mov x8, x3 /* install structure return */
++#ifdef FFI_GO_CLOSURES
++ mov x18, x5 /* install static chain */
++#endif
++ stp x3, x4, [x29, #16] /* save rvalue and flags */
+
-+ cmp r3, #FFI_TYPE_FLOAT
-+ fstseq s0, [r2]
-+ beq LSYM(Lepilogue_vfp)
-+
-+ cmp r3, #FFI_TYPE_DOUBLE
-+ fstdeq d0, [r2]
-+ beq LSYM(Lepilogue_vfp)
++ /* Load the vector argument passing registers, if necessary. */
++ tbz w4, #AARCH64_FLAG_ARG_V_BIT, 1f
++ ldp q0, q1, [sp, #0]
++ ldp q2, q3, [sp, #32]
++ ldp q4, q5, [sp, #64]
++ ldp q6, q7, [sp, #96]
++1:
++ /* Load the core argument passing registers, including
++ the structure return pointer. */
++ ldp x0, x1, [sp, #16*N_V_ARG_REG + 0]
++ ldp x2, x3, [sp, #16*N_V_ARG_REG + 16]
++ ldp x4, x5, [sp, #16*N_V_ARG_REG + 32]
++ ldp x6, x7, [sp, #16*N_V_ARG_REG + 48]
+
-+ cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT
-+ cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
-+ fstmiadeq r2, {d0-d3}
++ /* Deallocate the context, leaving the stacked arguments. */
++ add sp, sp, #CALL_CONTEXT_SIZE
+
-+LSYM(Lepilogue_vfp):
-+ RETLDM "r0-r3,fp"
++ blr x9 /* call fn */
+
-+.ffi_call_VFP_end:
-+ UNWIND .fnend
-+ .size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
++ ldp x3, x4, [x29, #16] /* reload rvalue and flags */
+
++ /* Partially deconstruct the stack frame. */
++ mov sp, x29
++ cfi_def_cfa_register (sp)
++ ldp x29, x30, [x29]
+
-+ARM_FUNC_START(ffi_closure_VFP)
-+ fstmfdd sp!, {d0-d7}
-+ @ r0-r3, then d0-d7
-+ UNWIND .pad #80
-+ add ip, sp, #80
-+ stmfd sp!, {ip, lr}
-+ UNWIND .save {r0, lr}
-+ add r2, sp, #72
-+ add r3, sp, #8
-+ UNWIND .pad #72
-+ sub sp, sp, #72
-+ str sp, [sp, #64]
-+ add r1, sp, #64
-+ bl CNAME(ffi_closure_inner)
-+
-+ cmp r0, #FFI_TYPE_INT
-+ beq .Lretint_vfp
-+
-+ cmp r0, #FFI_TYPE_FLOAT
-+ beq .Lretfloat_vfp
-+
-+ cmp r0, #FFI_TYPE_DOUBLE
-+ cmpne r0, #FFI_TYPE_LONGDOUBLE
-+ beq .Lretdouble_vfp
-+
-+ cmp r0, #FFI_TYPE_SINT64
-+ beq .Lretlonglong_vfp
-+
-+ cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT
-+ beq .Lretfloat_struct_vfp
-+
-+ cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
-+ beq .Lretdouble_struct_vfp
-+
-+.Lclosure_epilogue_vfp:
-+ add sp, sp, #72
-+ ldmfd sp, {sp, pc}
-+
-+.Lretfloat_vfp:
-+ flds s0, [sp]
-+ b .Lclosure_epilogue_vfp
-+.Lretdouble_vfp:
-+ fldd d0, [sp]
-+ b .Lclosure_epilogue_vfp
-+.Lretint_vfp:
-+ ldr r0, [sp]
-+ b .Lclosure_epilogue_vfp
-+.Lretlonglong_vfp:
-+ ldmia sp, {r0, r1}
-+ b .Lclosure_epilogue_vfp
-+.Lretfloat_struct_vfp:
-+ fldmiad sp, {d0-d1}
-+ b .Lclosure_epilogue_vfp
-+.Lretdouble_struct_vfp:
-+ fldmiad sp, {d0-d3}
-+ b .Lclosure_epilogue_vfp
-+
-+.ffi_closure_VFP_end:
-+ UNWIND .fnend
-+ .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
-+#endif
-+
-+ENTRY(ffi_arm_trampoline)
-+ stmfd sp!, {r0-r3}
-+ ldr r0, [pc]
-+ ldr pc, [pc]
++ /* Save the return value as directed. */
++ adr x5, 0f
++ and w4, w4, #AARCH64_RET_MASK
++ add x5, x5, x4, lsl #3
++ br x5
+
-+#if defined __ELF__ && defined __linux__
-+ .section .note.GNU-stack,"",%progbits
-+#endif
++ /* Note that each table entry is 2 insns, and thus 8 bytes.
++ For integer data, note that we're storing into ffi_arg
++ and therefore we want to extend to 64 bits; these types
++ have two consecutive entries allocated for them. */
++ .align 4
++0: ret /* VOID */
++ nop
++1: str x0, [x3] /* INT64 */
++ ret
++2: stp x0, x1, [x3] /* INT128 */
++ ret
++3: brk #1000 /* UNUSED */
++ ret
++4: brk #1000 /* UNUSED */
++ ret
++5: brk #1000 /* UNUSED */
++ ret
++6: brk #1000 /* UNUSED */
++ ret
++7: brk #1000 /* UNUSED */
++ ret
++8: st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */
++ ret
++9: st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */
++ ret
++10: stp s0, s1, [x3] /* S2 */
++ ret
++11: str s0, [x3] /* S1 */
++ ret
++12: st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */
++ ret
++13: st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */
++ ret
++14: stp d0, d1, [x3] /* D2 */
++ ret
++15: str d0, [x3] /* D1 */
++ ret
++16: str q3, [x3, #48] /* Q4 */
++ nop
++17: str q2, [x3, #32] /* Q3 */
++ nop
++18: stp q0, q1, [x3] /* Q2 */
++ ret
++19: str q0, [x3] /* Q1 */
++ ret
++20: uxtb w0, w0 /* UINT8 */
++ str x0, [x3]
++21: ret /* reserved */
++ nop
++22: uxth w0, w0 /* UINT16 */
++ str x0, [x3]
++23: ret /* reserved */
++ nop
++24: mov w0, w0 /* UINT32 */
++ str x0, [x3]
++25: ret /* reserved */
++ nop
++26: sxtb x0, w0 /* SINT8 */
++ str x0, [x3]
++27: ret /* reserved */
++ nop
++28: sxth x0, w0 /* SINT16 */
++ str x0, [x3]
++29: ret /* reserved */
++ nop
++30: sxtw x0, w0 /* SINT32 */
++ str x0, [x3]
++31: ret /* reserved */
++ nop
+
++ cfi_endproc
+
++ .globl CNAME(ffi_call_SYSV)
++#ifdef __ELF__
++ .type CNAME(ffi_call_SYSV), #function
++ .hidden CNAME(ffi_call_SYSV)
++ .size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S modified/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S
---- orig/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,4455 @@
-+#ifdef __arm__
-+
-+# GENERATED CODE - DO NOT EDIT
-+# This file was generated by src/arm/gentramp.sh
-+
-+# Copyright (c) 2010, Plausible Labs Cooperative, Inc.
-+#
-+# Permission is hereby granted, free of charge, to any person obtaining
-+# a copy of this software and associated documentation files (the
-+# Software''), to deal in the Software without restriction, including
-+# without limitation the rights to use, copy, modify, merge, publish,
-+# distribute, sublicense, and/or sell copies of the Software, and to
-+# permit persons to whom the Software is furnished to do so, subject to
-+# the following conditions:
-+#
-+# The above copyright notice and this permission notice shall be included
-+# in all copies or substantial portions of the Software.
-+#
-+# THE SOFTWARE IS PROVIDED AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+# DEALINGS IN THE SOFTWARE.
-+# -----------------------------------------------------------------------
+
-+.text
-+.align 12
-+.globl _ffi_closure_trampoline_table_page
-+_ffi_closure_trampoline_table_page:
++/* ffi_closure_SYSV
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Closure invocation glue. This is the low level code invoked directly by
++ the closure trampoline to setup and call a closure.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ On entry x17 points to a struct ffi_closure, x16 has been clobbered
++ all other registers are preserved.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ We allocate a call context and save the argument passing registers,
++ then invoked the generic C ffi_closure_SYSV_inner() function to do all
++ the real work, on return we load the result passing registers back from
++ the call context.
++*/
+
++#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ .align 4
++CNAME(ffi_closure_SYSV_V):
++ cfi_startproc
++ stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
++ cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
++ cfi_rel_offset (x29, 0)
++ cfi_rel_offset (x30, 8)
+
++ /* Save the argument passing vector registers. */
++ stp q0, q1, [sp, #16 + 0]
++ stp q2, q3, [sp, #16 + 32]
++ stp q4, q5, [sp, #16 + 64]
++ stp q6, q7, [sp, #16 + 96]
++ b 0f
++ cfi_endproc
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ .globl CNAME(ffi_closure_SYSV_V)
++#ifdef __ELF__
++ .type CNAME(ffi_closure_SYSV_V), #function
++ .hidden CNAME(ffi_closure_SYSV_V)
++ .size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ .align 4
++ cfi_startproc
++CNAME(ffi_closure_SYSV):
++ stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
++ cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
++ cfi_rel_offset (x29, 0)
++ cfi_rel_offset (x30, 8)
++0:
++ mov x29, sp
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Save the argument passing core registers. */
++ stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
++ stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
++ stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
++ stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
+
++ /* Load ffi_closure_inner arguments. */
++ ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */
++ ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */
++.Ldo_closure:
++ add x3, sp, #16 /* load context */
++ add x4, sp, #ffi_closure_SYSV_FS /* load stack */
++ add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
++ mov x6, x8 /* load struct_rval */
++ bl CNAME(ffi_closure_SYSV_inner)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Load the return value as directed. */
++ adr x1, 0f
++ and w0, w0, #AARCH64_RET_MASK
++ add x1, x1, x0, lsl #3
++ add x3, sp, #16+CALL_CONTEXT_SIZE
++ br x1
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Note that each table entry is 2 insns, and thus 8 bytes. */
++ .align 4
++0: b 99f /* VOID */
++ nop
++1: ldr x0, [x3] /* INT64 */
++ b 99f
++2: ldp x0, x1, [x3] /* INT128 */
++ b 99f
++3: brk #1000 /* UNUSED */
++ nop
++4: brk #1000 /* UNUSED */
++ nop
++5: brk #1000 /* UNUSED */
++ nop
++6: brk #1000 /* UNUSED */
++ nop
++7: brk #1000 /* UNUSED */
++ nop
++8: ldr s3, [x3, #12] /* S4 */
++ nop
++9: ldr s2, [x2, #8] /* S3 */
++ nop
++10: ldp s0, s1, [x3] /* S2 */
++ b 99f
++11: ldr s0, [x3] /* S1 */
++ b 99f
++12: ldr d3, [x3, #24] /* D4 */
++ nop
++13: ldr d2, [x3, #16] /* D3 */
++ nop
++14: ldp d0, d1, [x3] /* D2 */
++ b 99f
++15: ldr d0, [x3] /* D1 */
++ b 99f
++16: ldr q3, [x3, #48] /* Q4 */
++ nop
++17: ldr q2, [x3, #32] /* Q3 */
++ nop
++18: ldp q0, q1, [x3] /* Q2 */
++ b 99f
++19: ldr q0, [x3] /* Q1 */
++ b 99f
++20: ldrb w0, [x3, #BE(7)] /* UINT8 */
++ b 99f
++21: brk #1000 /* reserved */
++ nop
++22: ldrh w0, [x3, #BE(6)] /* UINT16 */
++ b 99f
++23: brk #1000 /* reserved */
++ nop
++24: ldr w0, [x3, #BE(4)] /* UINT32 */
++ b 99f
++25: brk #1000 /* reserved */
++ nop
++26: ldrsb x0, [x3, #BE(7)] /* SINT8 */
++ b 99f
++27: brk #1000 /* reserved */
++ nop
++28: ldrsh x0, [x3, #BE(6)] /* SINT16 */
++ b 99f
++29: brk #1000 /* reserved */
++ nop
++30: ldrsw x0, [x3, #BE(4)] /* SINT32 */
++ nop
++31: /* reserved */
++99: ldp x29, x30, [sp], #ffi_closure_SYSV_FS
++ cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
++ cfi_restore (x29)
++ cfi_restore (x30)
++ ret
++ cfi_endproc
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ .globl CNAME(ffi_closure_SYSV)
++#ifdef __ELF__
++ .type CNAME(ffi_closure_SYSV), #function
++ .hidden CNAME(ffi_closure_SYSV)
++ .size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
++#endif
+
++#if FFI_EXEC_TRAMPOLINE_TABLE
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifdef __MACH__
++#include
++ .align PAGE_MAX_SHIFT
++CNAME(ffi_closure_trampoline_table_page):
++ .rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE
++ adr x16, -PAGE_MAX_SIZE
++ ldp x17, x16, [x16]
++ br x16
++ nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller that 16 bytes */
++ .endr
++
++ .globl CNAME(ffi_closure_trampoline_table_page)
++ #ifdef __ELF__
++ .type CNAME(ffi_closure_trampoline_table_page), #function
++ .hidden CNAME(ffi_closure_trampoline_table_page)
++ .size CNAME(ffi_closure_trampoline_table_page), . - CNAME(ffi_closure_trampoline_table_page)
++ #endif
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef FFI_GO_CLOSURES
++ .align 4
++CNAME(ffi_go_closure_SYSV_V):
++ cfi_startproc
++ stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
++ cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
++ cfi_rel_offset (x29, 0)
++ cfi_rel_offset (x30, 8)
+
++ /* Save the argument passing vector registers. */
++ stp q0, q1, [sp, #16 + 0]
++ stp q2, q3, [sp, #16 + 32]
++ stp q4, q5, [sp, #16 + 64]
++ stp q6, q7, [sp, #16 + 96]
++ b 0f
++ cfi_endproc
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ .globl CNAME(ffi_go_closure_SYSV_V)
++#ifdef __ELF__
++ .type CNAME(ffi_go_closure_SYSV_V), #function
++ .hidden CNAME(ffi_go_closure_SYSV_V)
++ .size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ .align 4
++ cfi_startproc
++CNAME(ffi_go_closure_SYSV):
++ stp x29, x30, [sp, #-ffi_closure_SYSV_FS]!
++ cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
++ cfi_rel_offset (x29, 0)
++ cfi_rel_offset (x30, 8)
++0:
++ mov x29, sp
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Save the argument passing core registers. */
++ stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0]
++ stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16]
++ stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32]
++ stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48]
+
++ /* Load ffi_closure_inner arguments. */
++ ldp PTR_REG(0), PTR_REG(1), [x18, #PTR_SIZE]/* load cif, fn */
++ mov x2, x18 /* load user_data */
++ b .Ldo_closure
++ cfi_endproc
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ .globl CNAME(ffi_go_closure_SYSV)
++#ifdef __ELF__
++ .type CNAME(ffi_go_closure_SYSV), #function
++ .hidden CNAME(ffi_go_closure_SYSV)
++ .size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV)
++#endif
++#endif /* FFI_GO_CLOSURES */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if defined __ELF__ && defined __linux__
++ .section .note.GNU-stack,"",%progbits
++#endif
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#endif
+\ No newline at end of file
+diff -Nru orig/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c modified/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c
+--- orig/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/arm/ffi_armv7.c 2015-12-20 22:05:17.000000000 +0800
+@@ -0,0 +1,813 @@
++#ifdef __arm__
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* -----------------------------------------------------------------------
++ ffi.c - Copyright (c) 2011 Timothy Wall
++ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
++ Copyright (c) 2011 Anthony Green
++ Copyright (c) 2011 Free Software Foundation
++ Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ ARM Foreign Function Interface
+
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#include
++#include
++#include
++#include
++#include "internal.h"
+
++#if FFI_EXEC_TRAMPOLINE_TABLE
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifdef __MACH__
++#include
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#else
++extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
++#endif
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Forward declares. */
++static int vfp_type_p (const ffi_type *);
++static void layout_vfp_args (ffi_cif *);
+
++static void *
++ffi_align (ffi_type *ty, void *p)
++{
++ /* Align if necessary */
++ size_t alignment;
++#ifdef _WIN32_WCE
++ alignment = 4;
++#else
++ alignment = ty->alignment;
++ if (alignment < 4)
++ alignment = 4;
++#endif
++ return (void *) ALIGN (p, alignment);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++static size_t
++ffi_put_arg (ffi_type *ty, void *src, void *dst)
++{
++ size_t z = ty->size;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ switch (ty->type)
++ {
++ case FFI_TYPE_SINT8:
++ *(UINT32 *)dst = *(SINT8 *)src;
++ break;
++ case FFI_TYPE_UINT8:
++ *(UINT32 *)dst = *(UINT8 *)src;
++ break;
++ case FFI_TYPE_SINT16:
++ *(UINT32 *)dst = *(SINT16 *)src;
++ break;
++ case FFI_TYPE_UINT16:
++ *(UINT32 *)dst = *(UINT16 *)src;
++ break;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ case FFI_TYPE_INT:
++ case FFI_TYPE_SINT32:
++ case FFI_TYPE_UINT32:
++ case FFI_TYPE_POINTER:
++ case FFI_TYPE_FLOAT:
++ *(UINT32 *)dst = *(UINT32 *)src;
++ break;
+
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_UINT64:
++ case FFI_TYPE_DOUBLE:
++ *(UINT64 *)dst = *(UINT64 *)src;
++ break;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_COMPLEX:
++ memcpy (dst, src, z);
++ break;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ default:
++ abort();
++ }
+
++ return ALIGN (z, 4);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ffi_prep_args is called once stack space has been allocated
++ for the function's arguments.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ The vfp_space parameter is the load area for VFP regs, the return
++ value is cif->vfp_used (word bitset of VFP regs used for passing
++ arguments). These are only used for the VFP hard-float ABI.
++*/
++static void
++ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
++ void **avalue, char *argp)
++{
++ ffi_type **arg_types = cif->arg_types;
++ int i, n;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (flags == ARM_TYPE_STRUCT)
++ {
++ *(void **) argp = rvalue;
++ argp += 4;
++ }
+
++ for (i = 0, n = cif->nargs; i < n; i++)
++ {
++ ffi_type *ty = arg_types[i];
++ argp = ffi_align (ty, argp);
++ argp += ffi_put_arg (ty, avalue[i], argp);
++ }
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++static void
++ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
++ void **avalue, char *stack, char *vfp_space)
++{
++ ffi_type **arg_types = cif->arg_types;
++ int i, n, vi = 0;
++ char *argp, *regp, *eo_regp;
++ char stack_used = 0;
++ char done_with_regs = 0;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* The first 4 words on the stack are used for values
++ passed in core registers. */
++ regp = stack;
++ eo_regp = argp = regp + 16;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* If the function returns an FFI_TYPE_STRUCT in memory,
++ that address is passed in r0 to the function. */
++ if (flags == ARM_TYPE_STRUCT)
++ {
++ *(void **) regp = rvalue;
++ regp += 4;
++ }
+
++ for (i = 0, n = cif->nargs; i < n; i++)
++ {
++ ffi_type *ty = arg_types[i];
++ void *a = avalue[i];
++ int is_vfp_type = vfp_type_p (ty);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Allocated in VFP registers. */
++ if (vi < cif->vfp_nargs && is_vfp_type)
++ {
++ char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
++ ffi_put_arg (ty, a, vfp_slot);
++ continue;
++ }
++ /* Try allocating in core registers. */
++ else if (!done_with_regs && !is_vfp_type)
++ {
++ char *tregp = ffi_align (ty, regp);
++ size_t size = ty->size;
++ size = (size < 4) ? 4 : size; // pad
++ /* Check if there is space left in the aligned register
++ area to place the argument. */
++ if (tregp + size <= eo_regp)
++ {
++ regp = tregp + ffi_put_arg (ty, a, tregp);
++ done_with_regs = (regp == argp);
++ // ensure we did not write into the stack area
++ FFI_ASSERT (regp <= argp);
++ continue;
++ }
++ /* In case there are no arguments in the stack area yet,
++ the argument is passed in the remaining core registers
++ and on the stack. */
++ else if (!stack_used)
++ {
++ stack_used = 1;
++ done_with_regs = 1;
++ argp = tregp + ffi_put_arg (ty, a, tregp);
++ FFI_ASSERT (eo_regp < argp);
++ continue;
++ }
++ }
++ /* Base case, arguments are passed on the stack */
++ stack_used = 1;
++ argp = ffi_align (ty, argp);
++ argp += ffi_put_arg (ty, a, argp);
++ }
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Perform machine dependent cif processing */
++ffi_status
++ffi_prep_cif_machdep (ffi_cif *cif)
++{
++ int flags = 0, cabi = cif->abi;
++ size_t bytes = cif->bytes;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Map out the register placements of VFP register args. The VFP
++ hard-float calling conventions are slightly more sophisticated
++ than the base calling conventions, so we do it here instead of
++ in ffi_prep_args(). */
++ if (cabi == FFI_VFP)
++ layout_vfp_args (cif);
+
++ /* Set the return type flag */
++ switch (cif->rtype->type)
++ {
++ case FFI_TYPE_VOID:
++ flags = ARM_TYPE_VOID;
++ break;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ case FFI_TYPE_INT:
++ case FFI_TYPE_UINT8:
++ case FFI_TYPE_SINT8:
++ case FFI_TYPE_UINT16:
++ case FFI_TYPE_SINT16:
++ case FFI_TYPE_UINT32:
++ case FFI_TYPE_SINT32:
++ case FFI_TYPE_POINTER:
++ flags = ARM_TYPE_INT;
++ break;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ case FFI_TYPE_SINT64:
++ case FFI_TYPE_UINT64:
++ flags = ARM_TYPE_INT64;
++ break;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ case FFI_TYPE_FLOAT:
++ flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
++ break;
++ case FFI_TYPE_DOUBLE:
++ flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
++ break;
+
++ case FFI_TYPE_STRUCT:
++ case FFI_TYPE_COMPLEX:
++ if (cabi == FFI_VFP)
++ {
++ int h = vfp_type_p (cif->rtype);
++
++ flags = ARM_TYPE_VFP_N;
++ if (h == 0x100 + FFI_TYPE_FLOAT)
++ flags = ARM_TYPE_VFP_S;
++ if (h == 0x100 + FFI_TYPE_DOUBLE)
++ flags = ARM_TYPE_VFP_D;
++ if (h != 0)
++ break;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* A Composite Type not larger than 4 bytes is returned in r0.
++ A Composite Type larger than 4 bytes, or whose size cannot
++ be determined statically ... is stored in memory at an
++ address passed [in r0]. */
++ if (cif->rtype->size <= 4)
++ flags = ARM_TYPE_INT;
++ else
++ {
++ flags = ARM_TYPE_STRUCT;
++ bytes += 4;
++ }
++ break;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ default:
++ abort();
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Round the stack up to a multiple of 8 bytes. This isn't needed
++ everywhere, but it is on some platforms, and it doesn't harm anything
++ when it isn't needed. */
++ bytes = ALIGN (bytes, 8);
+
++ /* Minimum stack space is the 4 register arguments that we pop. */
++ if (bytes < 4*4)
++ bytes = 4*4;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ cif->bytes = bytes;
++ cif->flags = flags;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ return FFI_OK;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Perform machine dependent cif processing for variadic calls */
++ffi_status
++ffi_prep_cif_machdep_var (ffi_cif * cif,
++ unsigned int nfixedargs, unsigned int ntotalargs)
++{
++ /* VFP variadic calls actually use the SYSV ABI */
++ if (cif->abi == FFI_VFP)
++ cif->abi = FFI_SYSV;
+
++ return ffi_prep_cif_machdep (cif);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Prototypes for assembly functions, in sysv.S. */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++struct call_frame
++{
++ void *fp;
++ void *lr;
++ void *rvalue;
++ int flags;
++ void *closure;
++};
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++extern void ffi_call_SYSV (void *stack, struct call_frame *,
++ void (*fn) (void)) FFI_HIDDEN;
++extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
++ void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
+
++static void
++ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
++ void **avalue, void *closure)
++{
++ int flags = cif->flags;
++ ffi_type *rtype = cif->rtype;
++ size_t bytes, rsize, vfp_size;
++ char *stack, *vfp_space, *new_rvalue;
++ struct call_frame *frame;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ rsize = 0;
++ if (rvalue == NULL)
++ {
++ /* If the return value is a struct and we don't have a return
++ value address then we need to make one. Otherwise the return
++ value is in registers and we can ignore them. */
++ if (flags == ARM_TYPE_STRUCT)
++ rsize = rtype->size;
++ else
++ flags = ARM_TYPE_VOID;
++ }
++ else if (flags == ARM_TYPE_VFP_N)
++ {
++ /* Largest case is double x 4. */
++ rsize = 32;
++ }
++ else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
++ rsize = 4;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Largest case. */
++ vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ bytes = cif->bytes;
++ stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
+
++ vfp_space = NULL;
++ if (vfp_size)
++ {
++ vfp_space = stack;
++ stack += vfp_size;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ frame = (struct call_frame *)(stack + bytes);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ new_rvalue = rvalue;
++ if (rsize)
++ new_rvalue = (void *)(frame + 1);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ frame->rvalue = new_rvalue;
++ frame->flags = flags;
++ frame->closure = closure;
+
++ if (vfp_space)
++ {
++ ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
++ ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
++ }
++ else
++ {
++ ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
++ ffi_call_SYSV (stack, frame, fn);
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (rvalue && rvalue != new_rvalue)
++ memcpy (rvalue, new_rvalue, rtype->size);
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++void
++ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
++{
++ ffi_call_int (cif, fn, rvalue, avalue, NULL);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++void
++ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
++ void **avalue, void *closure)
++{
++ ffi_call_int (cif, fn, rvalue, avalue, closure);
++}
+
++static void *
++ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
++ char *argp, void **avalue)
++{
++ ffi_type **arg_types = cif->arg_types;
++ int i, n;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (cif->flags == ARM_TYPE_STRUCT)
++ {
++ rvalue = *(void **) argp;
++ argp += 4;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ for (i = 0, n = cif->nargs; i < n; i++)
++ {
++ ffi_type *ty = arg_types[i];
++ size_t z = ty->size;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ argp = ffi_align (ty, argp);
++ avalue[i] = (void *) argp;
++ argp += z;
++ }
+
++ return rvalue;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++static void *
++ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
++ char *vfp_space, void **avalue)
++{
++ ffi_type **arg_types = cif->arg_types;
++ int i, n, vi = 0;
++ char *argp, *regp, *eo_regp;
++ char done_with_regs = 0;
++ char stack_used = 0;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ regp = stack;
++ eo_regp = argp = regp + 16;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (cif->flags == ARM_TYPE_STRUCT)
++ {
++ rvalue = *(void **) regp;
++ regp += 4;
++ }
+
++ for (i = 0, n = cif->nargs; i < n; i++)
++ {
++ ffi_type *ty = arg_types[i];
++ int is_vfp_type = vfp_type_p (ty);
++ size_t z = ty->size;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (vi < cif->vfp_nargs && is_vfp_type)
++ {
++ avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
++ continue;
++ }
++ else if (!done_with_regs && !is_vfp_type)
++ {
++ char *tregp = ffi_align (ty, regp);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ z = (z < 4) ? 4 : z; // pad
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* If the arguments either fits into the registers or uses registers
++ and stack, while we haven't read other things from the stack */
++ if (tregp + z <= eo_regp || !stack_used)
++ {
++ /* Because we're little endian, this is what it turns into. */
++ avalue[i] = (void *) tregp;
++ regp = tregp + z;
++
++ /* If we read past the last core register, make sure we
++ have not read from the stack before and continue
++ reading after regp. */
++ if (regp > eo_regp)
++ {
++ FFI_ASSERT (!stack_used);
++ argp = regp;
++ }
++ if (regp >= eo_regp)
++ {
++ done_with_regs = 1;
++ stack_used = 1;
++ }
++ continue;
++ }
++ }
+
++ stack_used = 1;
++ argp = ffi_align (ty, argp);
++ avalue[i] = (void *) argp;
++ argp += z;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ return rvalue;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++struct closure_frame
++{
++ char vfp_space[8*8] __attribute__((aligned(8)));
++ char result[8*4];
++ char argp[];
++};
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++int FFI_HIDDEN
++ffi_closure_inner_SYSV (ffi_cif *cif,
++ void (*fun) (ffi_cif *, void *, void **, void *),
++ void *user_data,
++ struct closure_frame *frame)
++{
++ void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
++ void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
++ frame->argp, avalue);
++ fun (cif, rvalue, avalue, user_data);
++ return cif->flags;
++}
+
++int FFI_HIDDEN
++ffi_closure_inner_VFP (ffi_cif *cif,
++ void (*fun) (ffi_cif *, void *, void **, void *),
++ void *user_data,
++ struct closure_frame *frame)
++{
++ void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
++ void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
++ frame->vfp_space, avalue);
++ fun (cif, rvalue, avalue, user_data);
++ return cif->flags;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++void ffi_closure_SYSV (void) FFI_HIDDEN;
++void ffi_closure_VFP (void) FFI_HIDDEN;
++void ffi_go_closure_SYSV (void) FFI_HIDDEN;
++void ffi_go_closure_VFP (void) FFI_HIDDEN;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* the cif must already be prep'ed */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ffi_status
++ffi_prep_closure_loc (ffi_closure * closure,
++ ffi_cif * cif,
++ void (*fun) (ffi_cif *, void *, void **, void *),
++ void *user_data, void *codeloc)
++{
++ void (*closure_func) (void) = ffi_closure_SYSV;
+
++ if (cif->abi == FFI_VFP)
++ {
++ /* We only need take the vfp path if there are vfp arguments. */
++ if (cif->vfp_used)
++ closure_func = ffi_closure_VFP;
++ }
++ else if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if FFI_EXEC_TRAMPOLINE_TABLE
++ void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
++ config[0] = closure;
++ config[1] = closure_func;
++#else
++ memcpy (closure->tramp, ffi_arm_trampoline, 8);
++ __clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */
++ __clear_cache(codeloc, codeloc + 8); /* clear insn map */
++ *(void (**)(void))(closure->tramp + 8) = closure_func;
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ closure->cif = cif;
++ closure->fun = fun;
++ closure->user_data = user_data;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return FFI_OK;
++}
+
++ffi_status
++ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
++ void (*fun) (ffi_cif *, void *, void **, void *))
++{
++ void (*closure_func) (void) = ffi_go_closure_SYSV;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (cif->abi == FFI_VFP)
++ {
++ /* We only need take the vfp path if there are vfp arguments. */
++ if (cif->vfp_used)
++ closure_func = ffi_go_closure_VFP;
++ }
++ else if (cif->abi != FFI_SYSV)
++ return FFI_BAD_ABI;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ closure->tramp = closure_func;
++ closure->cif = cif;
++ closure->fun = fun;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return FFI_OK;
++}
+
++/* Below are routines for VFP hard-float support. */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* A subroutine of vfp_type_p. Given a structure type, return the type code
++ of the first non-structure element. Recurse for structure elements.
++ Return -1 if the structure is in fact empty, i.e. no nested elements. */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static int
++is_hfa0 (const ffi_type *ty)
++{
++ ffi_type **elements = ty->elements;
++ int i, ret = -1;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (elements != NULL)
++ for (i = 0; elements[i]; ++i)
++ {
++ ret = elements[i]->type;
++ if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
++ {
++ ret = is_hfa0 (elements[i]);
++ if (ret < 0)
++ continue;
++ }
++ break;
++ }
+
++ return ret;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* A subroutine of vfp_type_p. Given a structure type, return true if all
++ of the non-structure elements are the same as CANDIDATE. */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static int
++is_hfa1 (const ffi_type *ty, int candidate)
++{
++ ffi_type **elements = ty->elements;
++ int i;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (elements != NULL)
++ for (i = 0; elements[i]; ++i)
++ {
++ int t = elements[i]->type;
++ if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
++ {
++ if (!is_hfa1 (elements[i], candidate))
++ return 0;
++ }
++ else if (t != candidate)
++ return 0;
++ }
+
++ return 1;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Determine if TY is an homogenous floating point aggregate (HFA).
++ That is, a structure consisting of 1 to 4 members of all the same type,
++ where that type is a floating point scalar.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Returns non-zero iff TY is an HFA. The result is an encoded value where
++ bits 0-7 contain the type code, and bits 8-10 contain the element count. */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++static int
++vfp_type_p (const ffi_type *ty)
++{
++ ffi_type **elements;
++ int candidate, i;
++ size_t size, ele_count;
+
++ /* Quickest tests first. */
++ candidate = ty->type;
++ switch (ty->type)
++ {
++ default:
++ return 0;
++ case FFI_TYPE_FLOAT:
++ case FFI_TYPE_DOUBLE:
++ ele_count = 1;
++ goto done;
++ case FFI_TYPE_COMPLEX:
++ candidate = ty->elements[0]->type;
++ if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
++ return 0;
++ ele_count = 2;
++ goto done;
++ case FFI_TYPE_STRUCT:
++ break;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* No HFA types are smaller than 4 bytes, or larger than 32 bytes. */
++ size = ty->size;
++ if (size < 4 || size > 32)
++ return 0;
+
++ /* Find the type of the first non-structure member. */
++ elements = ty->elements;
++ candidate = elements[0]->type;
++ if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
++ {
++ for (i = 0; ; ++i)
++ {
++ candidate = is_hfa0 (elements[i]);
++ if (candidate >= 0)
++ break;
++ }
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* If the first member is not a floating point type, it's not an HFA.
++ Also quickly re-check the size of the structure. */
++ switch (candidate)
++ {
++ case FFI_TYPE_FLOAT:
++ ele_count = size / sizeof(float);
++ if (size != ele_count * sizeof(float))
++ return 0;
++ break;
++ case FFI_TYPE_DOUBLE:
++ ele_count = size / sizeof(double);
++ if (size != ele_count * sizeof(double))
++ return 0;
++ break;
++ default:
++ return 0;
++ }
++ if (ele_count > 4)
++ return 0;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Finally, make sure that all scalar elements are the same type. */
++ for (i = 0; elements[i]; ++i)
++ {
++ int t = elements[i]->type;
++ if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
++ {
++ if (!is_hfa1 (elements[i], candidate))
++ return 0;
++ }
++ else if (t != candidate)
++ return 0;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* All tests succeeded. Encode the result. */
++ done:
++ return (ele_count << 8) | candidate;
++}
+
++static int
++place_vfp_arg (ffi_cif *cif, int h)
++{
++ unsigned short reg = cif->vfp_reg_free;
++ int align = 1, nregs = h >> 8;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if ((h & 0xff) == FFI_TYPE_DOUBLE)
++ align = 2, nregs *= 2;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Align register number. */
++ if ((reg & 1) && align == 2)
++ reg++;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ while (reg + nregs <= 16)
++ {
++ int s, new_used = 0;
++ for (s = reg; s < reg + nregs; s++)
++ {
++ new_used |= (1 << s);
++ if (cif->vfp_used & (1 << s))
++ {
++ reg += align;
++ goto next_reg;
++ }
++ }
++ /* Found regs to allocate. */
++ cif->vfp_used |= new_used;
++ cif->vfp_args[cif->vfp_nargs++] = reg;
+
++ /* Update vfp_reg_free. */
++ if (cif->vfp_used & (1 << cif->vfp_reg_free))
++ {
++ reg += nregs;
++ while (cif->vfp_used & (1 << reg))
++ reg += 1;
++ cif->vfp_reg_free = reg;
++ }
++ return 0;
++ next_reg:;
++ }
++ // done, mark all regs as used
++ cif->vfp_reg_free = 16;
++ cif->vfp_used = 0xFFFF;
++ return 1;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++static void
++layout_vfp_args (ffi_cif * cif)
++{
++ int i;
++ /* Init VFP fields */
++ cif->vfp_used = 0;
++ cif->vfp_nargs = 0;
++ cif->vfp_reg_free = 0;
++ memset (cif->vfp_args, -1, 16); /* Init to -1. */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ for (i = 0; i < cif->nargs; i++)
++ {
++ int h = vfp_type_p (cif->arg_types[i]);
++ if (h && place_vfp_arg (cif, h) == 1)
++ break;
++ }
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++#endif
+\ No newline at end of file
+diff -Nru orig/Modules/_ctypes/libffi_ios/arm/internal.h modified/Modules/_ctypes/libffi_ios/arm/internal.h
+--- orig/Modules/_ctypes/libffi_ios/arm/internal.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/arm/internal.h 2015-12-20 19:03:21.000000000 +0800
+@@ -0,0 +1,7 @@
++#define ARM_TYPE_VFP_S 0
++#define ARM_TYPE_VFP_D 1
++#define ARM_TYPE_VFP_N 2
++#define ARM_TYPE_INT64 3
++#define ARM_TYPE_INT 4
++#define ARM_TYPE_VOID 5
++#define ARM_TYPE_STRUCT 6
+diff -Nru orig/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S modified/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S
+--- orig/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/arm/sysv_armv7.S 2015-12-20 22:31:41.000000000 +0800
+@@ -0,0 +1,388 @@
++#ifdef __arm__
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* -----------------------------------------------------------------------
++ sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
++ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ ARM Foreign Function Interface
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
+
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define LIBFFI_ASM
++#include
++#include
++#include
++#include "internal.h"
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */
++#ifndef __ARM_ARCH
++# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
++ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
++ || defined(__ARM_ARCH_7EM__)
++# define __ARM_ARCH 7
++# 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(__ARM_ARCH_6M__)
++# define __ARM_ARCH 6
++# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
++ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
++ || defined(__ARM_ARCH_5TEJ__)
++# define __ARM_ARCH 5
++# else
++# define __ARM_ARCH 4
++# endif
++#endif
+
++/* Conditionally compile unwinder directives. */
++#ifdef __ARM_EABI__
++# define UNWIND(...) __VA_ARGS__
++#else
++# define UNWIND(...)
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__)
++ .cfi_sections .debug_frame
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define CONCAT(a, b) CONCAT2(a, b)
++#define CONCAT2(a, b) a ## b
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef __USER_LABEL_PREFIX__
++# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X)
++#else
++# define CNAME(X) X
++#endif
++#ifdef __ELF__
++# define SIZE(X) .size CNAME(X), . - CNAME(X)
++# define TYPE(X, Y) .type CNAME(X), Y
++#else
++# define SIZE(X)
++# define TYPE(X, Y)
++#endif
+
++#define ARM_FUNC_START_LOCAL(name) \
++ .align 3; \
++ TYPE(CNAME(name), %function); \
++ CNAME(name):
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define ARM_FUNC_START(name) \
++ .globl CNAME(name); \
++ FFI_HIDDEN(CNAME(name)); \
++ ARM_FUNC_START_LOCAL(name)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define ARM_FUNC_END(name) \
++ SIZE(name)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Aid in defining a jump table with 8 bytes between entries. */
++/* ??? The clang assembler doesn't handle .if with symbolic expressions. */
++#ifdef __clang__
++# define E(index)
++#else
++# define E(index) \
++ .if . - 0b - 8*index; \
++ .error "type table out of sync"; \
++ .endif
++#endif
+
++ .text
++ .syntax unified
++ .arm
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifndef __clang__
++ /* We require interworking on LDM, which implies ARMv5T,
++ which implies the existance of BLX. */
++ .arch armv5t
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Note that we use STC and LDC to encode VFP instructions,
++ so that we do not need ".fpu vfp", nor get that added to
++ the object file attributes. These will not be executed
++ unless the FFI_VFP abi is used. */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ @ r0: stack
++ @ r1: frame
++ @ r2: fn
++ @ r3: vfp_used
+
++ARM_FUNC_START(ffi_call_VFP)
++ UNWIND(.fnstart)
++ cfi_startproc
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ cmp r3, #3 @ load only d0 if possible
++#ifdef __clang__
++ vldrle d0, [sp]
++ vldmgt sp, {d0-d7}
++#else
++ ldcle p11, cr0, [r0] @ vldrle d0, [sp]
++ ldcgt p11, cr0, [r0], {16} @ vldmgt sp, {d0-d7}
++#endif
++ add r0, r0, #64 @ discard the vfp register args
++ /* FALLTHRU */
++ARM_FUNC_END(ffi_call_VFP)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ARM_FUNC_START(ffi_call_SYSV)
++ stm r1, {fp, lr}
++ mov fp, r1
++
++ @ This is a bit of a lie wrt the origin of the unwind info, but
++ @ now we've got the usual frame pointer and two saved registers.
++ UNWIND(.save {fp,lr})
++ UNWIND(.setfp fp, sp)
++ cfi_def_cfa(fp, 8)
++ cfi_rel_offset(fp, 0)
++ cfi_rel_offset(lr, 4)
++
++ mov sp, r0 @ install the stack pointer
++ mov lr, r2 @ move the fn pointer out of the way
++ ldr ip, [fp, #16] @ install the static chain
++ ldmia sp!, {r0-r3} @ move first 4 parameters in registers.
++ blx lr @ call fn
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ @ Load r2 with the pointer to storage for the return value
++ @ Load r3 with the return type code
++ ldr r2, [fp, #8]
++ ldr r3, [fp, #12]
+
++ @ Deallocate the stack with the arguments.
++ mov sp, fp
++ cfi_def_cfa_register(sp)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ @ Store values stored in registers.
++ .align 3
++ add pc, pc, r3, lsl #3
++ nop
++0:
++E(ARM_TYPE_VFP_S)
++#ifdef __clang__
++ vstr s0, [r2]
++#else
++ stc p10, cr0, [r2] @ vstr s0, [r2]
++#endif
++ pop {fp,pc}
++E(ARM_TYPE_VFP_D)
++#ifdef __clang__
++ vstr d0, [r2]
++#else
++ stc p11, cr0, [r2] @ vstr d0, [r2]
++#endif
++ pop {fp,pc}
++E(ARM_TYPE_VFP_N)
++#ifdef __clang__
++ vstm r2, {d0-d3}
++#else
++ stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3}
++#endif
++ pop {fp,pc}
++E(ARM_TYPE_INT64)
++ str r1, [r2, #4]
++ nop
++E(ARM_TYPE_INT)
++ str r0, [r2]
++ pop {fp,pc}
++E(ARM_TYPE_VOID)
++ pop {fp,pc}
++ nop
++E(ARM_TYPE_STRUCT)
++ pop {fp,pc}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ cfi_endproc
++ UNWIND(.fnend)
++ARM_FUNC_END(ffi_call_SYSV)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++/*
++ int ffi_closure_inner_* (cif, fun, user_data, frame)
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ARM_FUNC_START(ffi_go_closure_SYSV)
++ cfi_startproc
++ stmdb sp!, {r0-r3} @ save argument regs
++ cfi_adjust_cfa_offset(16)
++ ldr r0, [ip, #4] @ load cif
++ ldr r1, [ip, #8] @ load fun
++ mov r2, ip @ load user_data
++ b 0f
++ cfi_endproc
++ARM_FUNC_END(ffi_go_closure_SYSV)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ARM_FUNC_START(ffi_closure_SYSV)
++ UNWIND(.fnstart)
++ cfi_startproc
++ stmdb sp!, {r0-r3} @ save argument regs
++ cfi_adjust_cfa_offset(16)
++
++#if FFI_EXEC_TRAMPOLINE_TABLE
++ ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure*
++#endif
++ ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif
++ ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun
++ ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data
++0:
++ add ip, sp, #16 @ compute entry sp
++ sub sp, sp, #64+32 @ allocate frame
++ cfi_adjust_cfa_offset(64+32)
++ stmdb sp!, {ip,lr}
++
++ /* Remember that EABI unwind info only applies at call sites.
++ We need do nothing except note the save of the stack pointer
++ and the link registers. */
++ UNWIND(.save {sp,lr})
++ cfi_adjust_cfa_offset(8)
++ cfi_rel_offset(lr, 4)
++
++ add r3, sp, #8 @ load frame
++ bl CNAME(ffi_closure_inner_SYSV)
++
++ @ Load values returned in registers.
++ add r2, sp, #8+64 @ load result
++ adr r3, CNAME(ffi_closure_ret)
++ add pc, r3, r0, lsl #3
++ cfi_endproc
++ UNWIND(.fnend)
++ARM_FUNC_END(ffi_closure_SYSV)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ARM_FUNC_START(ffi_go_closure_VFP)
++ cfi_startproc
++ stmdb sp!, {r0-r3} @ save argument regs
++ cfi_adjust_cfa_offset(16)
++ ldr r0, [ip, #4] @ load cif
++ ldr r1, [ip, #8] @ load fun
++ mov r2, ip @ load user_data
++ b 0f
++ cfi_endproc
++ARM_FUNC_END(ffi_go_closure_VFP)
+
++ARM_FUNC_START(ffi_closure_VFP)
++ UNWIND(.fnstart)
++ cfi_startproc
++ stmdb sp!, {r0-r3} @ save argument regs
++ cfi_adjust_cfa_offset(16)
++
++#if FFI_EXEC_TRAMPOLINE_TABLE
++ ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure*
++#endif
++ ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif
++ ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun
++ ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data
++0:
++ add ip, sp, #16
++ sub sp, sp, #64+32 @ allocate frame
++ cfi_adjust_cfa_offset(64+32)
++#ifdef __clang__
++ vstm sp, {d0-d7}
++#else
++ stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7}
++#endif
++ stmdb sp!, {ip,lr}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* See above. */
++ UNWIND(.save {sp,lr})
++ cfi_adjust_cfa_offset(8)
++ cfi_rel_offset(lr, 4)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ add r3, sp, #8 @ load frame
++ bl CNAME(ffi_closure_inner_VFP)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ @ Load values returned in registers.
++ add r2, sp, #8+64 @ load result
++ adr r3, CNAME(ffi_closure_ret)
++ add pc, r3, r0, lsl #3
++ cfi_endproc
++ UNWIND(.fnend)
++ARM_FUNC_END(ffi_closure_VFP)
+
++/* Load values returned in registers for both closure entry points.
++ Note that we use LDM with SP in the register set. This is deprecated
++ by ARM, but not yet unpredictable. */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ARM_FUNC_START_LOCAL(ffi_closure_ret)
++ cfi_startproc
++ cfi_rel_offset(sp, 0)
++ cfi_rel_offset(lr, 4)
++0:
++E(ARM_TYPE_VFP_S)
++#ifdef __clang__
++ vldr s0, [r2]
++#else
++ ldc p10, cr0, [r2] @ vldr s0, [r2]
++#endif
++ ldm sp, {sp,pc}
++E(ARM_TYPE_VFP_D)
++#ifdef __clang__
++ vldr d0, [r2]
++#else
++ ldc p11, cr0, [r2] @ vldr d0, [r2]
++#endif
++ ldm sp, {sp,pc}
++E(ARM_TYPE_VFP_N)
++#ifdef __clang__
++ vldm r2, {d0-d3}
++#else
++ ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3}
++#endif
++ ldm sp, {sp,pc}
++E(ARM_TYPE_INT64)
++ ldr r1, [r2, #4]
++ nop
++E(ARM_TYPE_INT)
++ ldr r0, [r2]
++ ldm sp, {sp,pc}
++E(ARM_TYPE_VOID)
++ ldm sp, {sp,pc}
++ nop
++E(ARM_TYPE_STRUCT)
++ ldm sp, {sp,pc}
++ cfi_endproc
++ARM_FUNC_END(ffi_closure_ret)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if FFI_EXEC_TRAMPOLINE_TABLE
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef __MACH__
++#include
+
++.align PAGE_MAX_SHIFT
++ARM_FUNC_START(ffi_closure_trampoline_table_page)
++.rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE
++ adr ip, #-PAGE_MAX_SIZE @ the config page is PAGE_MAX_SIZE behind the trampoline page
++ sub ip, #8 @ account for pc bias
++ ldr pc, [ip, #4] @ jump to ffi_closure_SYSV or ffi_closure_VFP
++.endr
++ARM_FUNC_END(ffi_closure_trampoline_table_page)
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#else
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ARM_FUNC_START(ffi_arm_trampoline)
++0: adr ip, 0b
++ ldr pc, 1f
++1: .long 0
++ARM_FUNC_END(ffi_arm_trampoline)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
+
++#if defined __ELF__ && defined __linux__
++ .section .note.GNU-stack,"",%progbits
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#endif
+\ No newline at end of file
+diff -Nru orig/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S modified/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S
+--- orig/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/arm/trampoline_armv7.S 2015-12-20 18:50:24.000000000 +0800
+@@ -0,0 +1,5 @@
++#ifdef __arm__
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#endif
+\ No newline at end of file
+diff -Nru orig/Modules/_ctypes/libffi_ios/closures.c modified/Modules/_ctypes/libffi_ios/closures.c
+--- orig/Modules/_ctypes/libffi_ios/closures.c 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/closures.c 2015-12-20 22:04:37.000000000 +0800
+@@ -0,0 +1,925 @@
++/* -----------------------------------------------------------------------
++ closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
++ Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
++ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Code to allocate and deallocate memory for closures.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
+
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if defined __linux__ && !defined _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#include
++#include
++#include
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
++# if __gnu_linux__ && !defined(__ANDROID__)
++/* This macro indicates it may be forbidden to map anonymous memory
++ with both write and execute permission. Code compiled when this
++ option is defined will attempt to map such pages once, but if it
++ fails, it falls back to creating a temporary file in a writable and
++ executable filesystem and mapping pages from it into separate
++ locations in the virtual memory space, one location writable and
++ another executable. */
++# define FFI_MMAP_EXEC_WRIT 1
++# define HAVE_MNTENT 1
++# endif
++# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
++/* Windows systems may have Data Execution Protection (DEP) enabled,
++ which requires the use of VirtualMalloc/VirtualFree to alloc/free
++ executable memory. */
++# define FFI_MMAP_EXEC_WRIT 1
++# endif
++#endif
+
++#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
++# ifdef __linux__
++/* When defined to 1 check for SELinux and if SELinux is active,
++ don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
++ might cause audit messages. */
++# define FFI_MMAP_EXEC_SELINUX 1
++# endif
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if FFI_CLOSURES
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if FFI_EXEC_TRAMPOLINE_TABLE
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef __MACH__
+
++#include
++#include
++#include
++#include
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++extern void *ffi_closure_trampoline_table_page;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++typedef struct ffi_trampoline_table ffi_trampoline_table;
++typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++struct ffi_trampoline_table
++{
++ /* contiguous writable and executable pages */
++ vm_address_t config_page;
++ vm_address_t trampoline_page;
+
++ /* free list tracking */
++ uint16_t free_count;
++ ffi_trampoline_table_entry *free_list;
++ ffi_trampoline_table_entry *free_list_pool;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ ffi_trampoline_table *prev;
++ ffi_trampoline_table *next;
++};
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++struct ffi_trampoline_table_entry
++{
++ void *(*trampoline) ();
++ ffi_trampoline_table_entry *next;
++};
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Total number of trampolines that fit in one trampoline table */
++#define FFI_TRAMPOLINE_COUNT (PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE)
+
++static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
++static ffi_trampoline_table *ffi_trampoline_tables = NULL;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++static ffi_trampoline_table *
++ffi_trampoline_table_alloc ()
++{
++ ffi_trampoline_table *table = NULL;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Loop until we can allocate two contiguous pages */
++ while (table == NULL)
++ {
++ vm_address_t config_page = 0x0;
++ kern_return_t kt;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Try to allocate two pages */
++ kt =
++ vm_allocate (mach_task_self (), &config_page, PAGE_MAX_SIZE * 2,
++ VM_FLAGS_ANYWHERE);
++ if (kt != KERN_SUCCESS)
++ {
++ fprintf (stderr, "vm_allocate() failure: %d at %s:%d\n", kt,
++ __FILE__, __LINE__);
++ break;
++ }
+
++ /* Now drop the second half of the allocation to make room for the trampoline table */
++ vm_address_t trampoline_page = config_page + PAGE_MAX_SIZE;
++ kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_MAX_SIZE);
++ if (kt != KERN_SUCCESS)
++ {
++ fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
++ __FILE__, __LINE__);
++ break;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Remap the trampoline table to directly follow the config page */
++ vm_prot_t cur_prot;
++ vm_prot_t max_prot;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ vm_address_t trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page;
++#ifdef __arm__
++ /* ffi_closure_trampoline_table_page can be thumb-biased on some ARM archs */
++ trampoline_page_template &= ~1UL;
++#endif
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ kt =
++ vm_remap (mach_task_self (), &trampoline_page, PAGE_MAX_SIZE, 0x0, FALSE,
++ mach_task_self (), trampoline_page_template, FALSE,
++ &cur_prot, &max_prot, VM_INHERIT_SHARE);
+
++ /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
++ if (kt != KERN_SUCCESS)
++ {
++ /* Log unexpected failures */
++ if (kt != KERN_NO_SPACE)
++ {
++ fprintf (stderr, "vm_remap() failure: %d at %s:%d\n", kt,
++ __FILE__, __LINE__);
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
++ continue;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* We have valid trampoline and config pages */
++ table = calloc (1, sizeof (ffi_trampoline_table));
++ table->free_count = FFI_TRAMPOLINE_COUNT;
++ table->config_page = config_page;
++ table->trampoline_page = trampoline_page;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Create and initialize the free list */
++ table->free_list_pool =
++ calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry));
+
++ uint16_t i;
++ for (i = 0; i < table->free_count; i++)
++ {
++ ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
++ entry->trampoline =
++ (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (i < table->free_count - 1)
++ entry->next = &table->free_list_pool[i + 1];
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ table->free_list = table->free_list_pool;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return table;
++}
+
++void *
++ffi_closure_alloc (size_t size, void **code)
++{
++ /* Create the closure */
++ ffi_closure *closure = malloc (size);
++ if (closure == NULL)
++ return NULL;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ pthread_mutex_lock (&ffi_trampoline_lock);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Check for an active trampoline table with available entries. */
++ ffi_trampoline_table *table = ffi_trampoline_tables;
++ if (table == NULL || table->free_list == NULL)
++ {
++ table = ffi_trampoline_table_alloc ();
++ if (table == NULL)
++ {
++ free (closure);
++ return NULL;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Insert the new table at the top of the list */
++ table->next = ffi_trampoline_tables;
++ if (table->next != NULL)
++ table->next->prev = table;
+
++ ffi_trampoline_tables = table;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Claim the free entry */
++ ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
++ ffi_trampoline_tables->free_list = entry->next;
++ ffi_trampoline_tables->free_count--;
++ entry->next = NULL;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ pthread_mutex_unlock (&ffi_trampoline_lock);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Initialize the return values */
++ *code = entry->trampoline;
++ closure->trampoline_table = table;
++ closure->trampoline_table_entry = entry;
+
++ return closure;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++void
++ffi_closure_free (void *ptr)
++{
++ ffi_closure *closure = ptr;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ pthread_mutex_lock (&ffi_trampoline_lock);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Fetch the table and entry references */
++ ffi_trampoline_table *table = closure->trampoline_table;
++ ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
+
++ /* Return the entry to the free list */
++ entry->next = table->free_list;
++ table->free_list = entry;
++ table->free_count++;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* If all trampolines within this table are free, and at least one other table exists, deallocate
++ * the table */
++ if (table->free_count == FFI_TRAMPOLINE_COUNT
++ && ffi_trampoline_tables != table)
++ {
++ /* Remove from the list */
++ if (table->prev != NULL)
++ table->prev->next = table->next;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (table->next != NULL)
++ table->next->prev = table->prev;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Deallocate pages */
++ kern_return_t kt;
++ kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
++ if (kt != KERN_SUCCESS)
++ fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
++ __FILE__, __LINE__);
+
++ kt =
++ vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
++ if (kt != KERN_SUCCESS)
++ fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
++ __FILE__, __LINE__);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Deallocate free list */
++ free (table->free_list_pool);
++ free (table);
++ }
++ else if (ffi_trampoline_tables != table)
++ {
++ /* Otherwise, bump this table to the top of the list */
++ table->prev = NULL;
++ table->next = ffi_trampoline_tables;
++ if (ffi_trampoline_tables != NULL)
++ ffi_trampoline_tables->prev = table;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ ffi_trampoline_tables = table;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ pthread_mutex_unlock (&ffi_trampoline_lock);
+
++ /* Free the closure */
++ free (closure);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
+
++#define USE_LOCKS 1
++#define USE_DL_PREFIX 1
++#ifdef __GNUC__
++#ifndef USE_BUILTIN_FFS
++#define USE_BUILTIN_FFS 1
++#endif
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* We need to use mmap, not sbrk. */
++#define HAVE_MORECORE 0
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* We could, in theory, support mremap, but it wouldn't buy us anything. */
++#define HAVE_MREMAP 0
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* We have no use for this, so save some code and data. */
++#define NO_MALLINFO 1
+
++/* We need all allocations to be in regular segments, otherwise we
++ lose track of the corresponding code address. */
++#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Don't allocate more than a page unless needed. */
++#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if FFI_CLOSURE_TEST
++/* Don't release single pages, to avoid a worst-case scenario of
++ continuously allocating and releasing single pages, but release
++ pairs of pages, which should do just as well given that allocations
++ are likely to be small. */
++#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
++#endif
+
++#include
++#include
++#include
++#include
++#ifndef _MSC_VER
++#include
++#endif
++#include
++#include
++#if !defined(X86_WIN32) && !defined(X86_WIN64)
++#ifdef HAVE_MNTENT
++#include
++#endif /* HAVE_MNTENT */
++#include
++#include
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* We don't want sys/mman.h to be included after we redefine mmap and
++ dlmunmap. */
++#include
++#define LACKS_SYS_MMAN_H 1
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if FFI_MMAP_EXEC_SELINUX
++#include
++#include
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++static int selinux_enabled = -1;
+
++static int
++selinux_enabled_check (void)
++{
++ struct statfs sfs;
++ FILE *f;
++ char *buf = NULL;
++ size_t len = 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (statfs ("/selinux", &sfs) >= 0
++ && (unsigned int) sfs.f_type == 0xf97cff8cU)
++ return 1;
++ f = fopen ("/proc/mounts", "r");
++ if (f == NULL)
++ return 0;
++ while (getline (&buf, &len, f) >= 0)
++ {
++ char *p = strchr (buf, ' ');
++ if (p == NULL)
++ break;
++ p = strchr (p + 1, ' ');
++ if (p == NULL)
++ break;
++ if (strncmp (p + 1, "selinuxfs ", 10) == 0)
++ {
++ free (buf);
++ fclose (f);
++ return 1;
++ }
++ }
++ free (buf);
++ fclose (f);
++ return 0;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
++ : (selinux_enabled = selinux_enabled_check ()))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#else
+
++#define is_selinux_enabled() 0
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#endif /* !FFI_MMAP_EXEC_SELINUX */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
++#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
++#include
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++static int emutramp_enabled = -1;
+
++static int
++emutramp_enabled_check (void)
++{
++ char *buf = NULL;
++ size_t len = 0;
++ FILE *f;
++ int ret;
++ f = fopen ("/proc/self/status", "r");
++ if (f == NULL)
++ return 0;
++ ret = 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ while (getline (&buf, &len, f) != -1)
++ if (!strncmp (buf, "PaX:", 4))
++ {
++ char emutramp;
++ if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
++ ret = (emutramp == 'E');
++ break;
++ }
++ free (buf);
++ fclose (f);
++ return ret;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
++ : (emutramp_enabled = emutramp_enabled_check ()))
++#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#elif defined (__CYGWIN__) || defined(__INTERIX)
+
++#include
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Cygwin is Linux-like, but not quite that Linux-like. */
++#define is_selinux_enabled() 0
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
++#define is_emutramp_enabled() 0
++#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
++/* Declare all functions defined in dlmalloc.c as static. */
++static void *dlmalloc(size_t);
++static void dlfree(void*);
++static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
++static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
++static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
++static void *dlvalloc(size_t) MAYBE_UNUSED;
++static int dlmallopt(int, int) MAYBE_UNUSED;
++static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
++static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
++static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
++static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
++static void *dlpvalloc(size_t) MAYBE_UNUSED;
++static int dlmalloc_trim(size_t) MAYBE_UNUSED;
++static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
++static void dlmalloc_stats(void) MAYBE_UNUSED;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
++/* Use these for mmap and munmap within dlmalloc.c. */
++static void *dlmmap(void *, size_t, int, int, int, off_t);
++static int dlmunmap(void *, size_t);
++#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define mmap dlmmap
++#define munmap dlmunmap
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#include "dlmalloc.c"
+
++#undef mmap
++#undef munmap
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* A mutex used to synchronize access to *exec* variables in this file. */
++static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* A file descriptor of a temporary file from which we'll map
++ executable pages. */
++static int execfd = -1;
+
++/* The amount of space already allocated from the temporary file. */
++static size_t execsize = 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Open a temporary file name, and immediately unlink it. */
++static int
++open_temp_exec_file_name (char *name, int flags)
++{
++ int fd;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#ifdef HAVE_MKOSTEMP
++ fd = mkostemp (name, flags);
++#else
++ fd = mkstemp (name);
++#endif
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (fd != -1)
++ unlink (name);
+
++ return fd;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Open a temporary file in the named directory. */
++static int
++open_temp_exec_file_dir (const char *dir)
++{
++ static const char suffix[] = "/ffiXXXXXX";
++ int lendir, flags;
++ char *tempname;
++#ifdef O_TMPFILE
++ int fd;
++#endif
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#ifdef O_CLOEXEC
++ flags = O_CLOEXEC;
++#else
++ flags = 0;
++#endif
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef O_TMPFILE
++ fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
++ /* If the running system does not support the O_TMPFILE flag then retry without it. */
++ if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
++ return fd;
++ } else {
++ errno = 0;
++ }
++#endif
+
++ lendir = strlen (dir);
++ tempname = __builtin_alloca (lendir + sizeof (suffix));
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (!tempname)
++ return -1;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ memcpy (tempname, dir, lendir);
++ memcpy (tempname + lendir, suffix, sizeof (suffix));
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return open_temp_exec_file_name (tempname, flags);
++}
+
++/* Open a temporary file in the directory in the named environment
++ variable. */
++static int
++open_temp_exec_file_env (const char *envvar)
++{
++ const char *value = getenv (envvar);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (!value)
++ return -1;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ return open_temp_exec_file_dir (value);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef HAVE_MNTENT
++/* Open a temporary file in an executable and writable mount point
++ listed in the mounts file. Subsequent calls with the same mounts
++ keep searching for mount points in the same file. Providing NULL
++ as the mounts file closes the file. */
++static int
++open_temp_exec_file_mnt (const char *mounts)
++{
++ static const char *last_mounts;
++ static FILE *last_mntent;
+
++ if (mounts != last_mounts)
++ {
++ if (last_mntent)
++ endmntent (last_mntent);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ last_mounts = mounts;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (mounts)
++ last_mntent = setmntent (mounts, "r");
++ else
++ last_mntent = NULL;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (!last_mntent)
++ return -1;
+
++ for (;;)
++ {
++ int fd;
++ struct mntent mnt;
++ char buf[MAXPATHLEN * 3];
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL)
++ return -1;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (hasmntopt (&mnt, "ro")
++ || hasmntopt (&mnt, "noexec")
++ || access (mnt.mnt_dir, W_OK))
++ continue;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ fd = open_temp_exec_file_dir (mnt.mnt_dir);
+
++ if (fd != -1)
++ return fd;
++ }
++}
++#endif /* HAVE_MNTENT */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Instructions to look for a location to hold a temporary file that
++ can be mapped in for execution. */
++static struct
++{
++ int (*func)(const char *);
++ const char *arg;
++ int repeat;
++} open_temp_exec_file_opts[] = {
++ { open_temp_exec_file_env, "TMPDIR", 0 },
++ { open_temp_exec_file_dir, "/tmp", 0 },
++ { open_temp_exec_file_dir, "/var/tmp", 0 },
++ { open_temp_exec_file_dir, "/dev/shm", 0 },
++ { open_temp_exec_file_env, "HOME", 0 },
++#ifdef HAVE_MNTENT
++ { open_temp_exec_file_mnt, "/etc/mtab", 1 },
++ { open_temp_exec_file_mnt, "/proc/mounts", 1 },
++#endif /* HAVE_MNTENT */
++};
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Current index into open_temp_exec_file_opts. */
++static int open_temp_exec_file_opts_idx = 0;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Reset a current multi-call func, then advances to the next entry.
++ If we're at the last, go back to the first and return nonzero,
++ otherwise return zero. */
++static int
++open_temp_exec_file_opts_next (void)
++{
++ if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
++ open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
+
++ open_temp_exec_file_opts_idx++;
++ if (open_temp_exec_file_opts_idx
++ == (sizeof (open_temp_exec_file_opts)
++ / sizeof (*open_temp_exec_file_opts)))
++ {
++ open_temp_exec_file_opts_idx = 0;
++ return 1;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ return 0;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Return a file descriptor of a temporary zero-sized file in a
++ writable and executable filesystem. */
++static int
++open_temp_exec_file (void)
++{
++ int fd;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ do
++ {
++ fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
++ (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
+
++ if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
++ || fd == -1)
++ {
++ if (open_temp_exec_file_opts_next ())
++ break;
++ }
++ }
++ while (fd == -1);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ return fd;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Map in a chunk of memory from the temporary exec file into separate
++ locations in the virtual memory address space, one writable and one
++ executable. Returns the address of the writable portion, after
++ storing an offset to the corresponding executable portion at the
++ last word of the requested chunk. */
++static void *
++dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
++{
++ void *ptr;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (execfd == -1)
++ {
++ open_temp_exec_file_opts_idx = 0;
++ retry_open:
++ execfd = open_temp_exec_file ();
++ if (execfd == -1)
++ return MFAIL;
++ }
+
++ offset = execsize;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (ftruncate (execfd, offset + length))
++ return MFAIL;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
++ flags |= MAP_SHARED;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
++ flags, execfd, offset);
++ if (ptr == MFAIL)
++ {
++ if (!offset)
++ {
++ close (execfd);
++ goto retry_open;
++ }
++ ftruncate (execfd, offset);
++ return MFAIL;
++ }
++ else if (!offset
++ && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
++ open_temp_exec_file_opts_next ();
+
++ start = mmap (start, length, prot, flags, execfd, offset);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (start == MFAIL)
++ {
++ munmap (ptr, length);
++ ftruncate (execfd, offset);
++ return start;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ execsize += length;
+
++ return start;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Map in a writable and executable chunk of memory if possible.
++ Failing that, fall back to dlmmap_locked. */
++static void *
++dlmmap (void *start, size_t length, int prot,
++ int flags, int fd, off_t offset)
++{
++ void *ptr;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ assert (start == NULL && length % malloc_getpagesize == 0
++ && prot == (PROT_READ | PROT_WRITE)
++ && flags == (MAP_PRIVATE | MAP_ANONYMOUS)
++ && fd == -1 && offset == 0);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if FFI_CLOSURE_TEST
++ printf ("mapping in %zi\n", length);
++#endif
+
++ if (execfd == -1 && is_emutramp_enabled ())
++ {
++ ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
++ return ptr;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (execfd == -1 && !is_selinux_enabled ())
++ {
++ ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
++ /* Cool, no need to mess with separate segments. */
++ return ptr;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* If MREMAP_DUP is ever introduced and implemented, try mmap
++ with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
++ MREMAP_DUP and prot at this point. */
++ }
+
++ if (execsize == 0 || execfd == -1)
++ {
++ pthread_mutex_lock (&open_temp_exec_file_mutex);
++ ptr = dlmmap_locked (start, length, prot, flags, offset);
++ pthread_mutex_unlock (&open_temp_exec_file_mutex);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ return ptr;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ return dlmmap_locked (start, length, prot, flags, offset);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Release memory at the given address, as well as the corresponding
++ executable page if it's separate. */
++static int
++dlmunmap (void *start, size_t length)
++{
++ /* We don't bother decreasing execsize or truncating the file, since
++ we can't quite tell whether we're unmapping the end of the file.
++ We don't expect frequent deallocation anyway. If we did, we
++ could locate pages in the file by writing to the pages being
++ deallocated and checking that the file contents change.
++ Yuck. */
++ msegmentptr seg = segment_holding (gm, start);
++ void *code;
+
++#if FFI_CLOSURE_TEST
++ printf ("unmapping %zi\n", length);
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (seg && (code = add_segment_exec_offset (start, seg)) != start)
++ {
++ int ret = munmap (code, length);
++ if (ret)
++ return ret;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ return munmap (start, length);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if FFI_CLOSURE_FREE_CODE
++/* Return segment holding given code address. */
++static msegmentptr
++segment_holding_code (mstate m, char* addr)
++{
++ msegmentptr sp = &m->seg;
++ for (;;) {
++ if (addr >= add_segment_exec_offset (sp->base, sp)
++ && addr < add_segment_exec_offset (sp->base, sp) + sp->size)
++ return sp;
++ if ((sp = sp->next) == 0)
++ return 0;
++ }
++}
++#endif
+
++#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Allocate a chunk of memory with the given size. Returns a pointer
++ to the writable address, and sets *CODE to the executable
++ corresponding virtual address. */
++void *
++ffi_closure_alloc (size_t size, void **code)
++{
++ void *ptr;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (!code)
++ return NULL;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ ptr = dlmalloc (size);
+
++ if (ptr)
++ {
++ msegmentptr seg = segment_holding (gm, ptr);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ *code = add_segment_exec_offset (ptr, seg);
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ return ptr;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Release a chunk of memory allocated with ffi_closure_alloc. If
++ FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
++ writable or the executable address given. Otherwise, only the
++ writable address can be provided here. */
++void
++ffi_closure_free (void *ptr)
++{
++#if FFI_CLOSURE_FREE_CODE
++ msegmentptr seg = segment_holding_code (gm, ptr);
+
++ if (seg)
++ ptr = sub_segment_exec_offset (ptr, seg);
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ dlfree (ptr);
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if FFI_CLOSURE_TEST
++/* Do some internal sanity testing to make sure allocation and
++ deallocation of pages are working as intended. */
++int main ()
++{
++ void *p[3];
++#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
++#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
++ GET (0, malloc_getpagesize / 2);
++ GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
++ PUT (1);
++ GET (1, 2 * malloc_getpagesize);
++ GET (2, malloc_getpagesize / 2);
++ PUT (1);
++ PUT (0);
++ PUT (2);
++ return 0;
++}
++#endif /* FFI_CLOSURE_TEST */
++# else /* ! FFI_MMAP_EXEC_WRIT */
+
++/* On many systems, memory returned by malloc is writable and
++ executable, so just use it. */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#include
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++void *
++ffi_closure_alloc (size_t size, void **code)
++{
++ if (!code)
++ return NULL;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return *code = malloc (size);
++}
+
++void
++ffi_closure_free (void *ptr)
++{
++ free (ptr);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++# endif /* ! FFI_MMAP_EXEC_WRIT */
++#endif /* FFI_CLOSURES */
+diff -Nru orig/Modules/_ctypes/libffi_ios/debug.c modified/Modules/_ctypes/libffi_ios/debug.c
+--- orig/Modules/_ctypes/libffi_ios/debug.c 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/debug.c 2015-12-20 22:33:34.000000000 +0800
+@@ -0,0 +1,64 @@
++/* -----------------------------------------------------------------------
++ debug.c - Copyright (c) 1996 Red Hat, Inc.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files (the
++ ``Software''), to deal in the Software without restriction, including
++ without limitation the rights to use, copy, modify, merge, publish,
++ distribute, sublicense, and/or sell copies of the Software, and to
++ permit persons to whom the Software is furnished to do so, subject to
++ the following conditions:
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ The above copyright notice and this permission notice shall be included
++ in all copies or substantial portions of the Software.
+
++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ DEALINGS IN THE SOFTWARE.
++ ----------------------------------------------------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#include
++#include
++#include
++#include
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* General debugging routines */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++void ffi_stop_here(void)
++{
++ /* This function is only useful for debugging purposes.
++ Place a breakpoint on ffi_stop_here to be notified of
++ significant events. */
++}
+
++/* This function should only be called via the FFI_ASSERT() macro */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++void ffi_assert(char *expr, char *file, int line)
++{
++ fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line);
++ ffi_stop_here();
++ abort();
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Perform a sanity check on an ffi_type structure */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++void ffi_type_test(ffi_type *a, char *file, int line)
++{
++ FFI_ASSERT_AT(a != NULL, file, line);
++
++ FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line);
++ FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line);
++ FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line);
++ FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX)
++ || a->elements != NULL, file, line);
++ FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX
++ || (a->elements != NULL
++ && a->elements[0] != NULL && a->elements[1] == NULL),
++ file, line);
+
++}
+diff -Nru orig/Modules/_ctypes/libffi_ios/dlmalloc.c modified/Modules/_ctypes/libffi_ios/dlmalloc.c
+--- orig/Modules/_ctypes/libffi_ios/dlmalloc.c 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/dlmalloc.c 2015-12-20 18:49:03.000000000 +0800
+@@ -0,0 +1,5161 @@
++/*
++ This is a version (aka dlmalloc) of malloc/free/realloc written by
++ Doug Lea and released to the public domain, as explained at
++ http://creativecommons.org/licenses/publicdomain. Send questions,
++ comments, complaints, performance data, etc to dl@cs.oswego.edu
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Note: There may be an updated version of this malloc obtainable at
++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
++ Check before installing!
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++* Quickstart
+
++ This library is all in one file to simplify the most common usage:
++ ftp it, compile it (-O3), and link it into another program. All of
++ the compile-time options default to reasonable values for use on
++ most platforms. You might later want to step through various
++ compile-time and dynamic tuning options.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ For convenience, an include file for code using this malloc is at:
++ ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
++ You don't really need this .h file unless you call functions not
++ defined in your system include files. The .h file contains only the
++ excerpts from this file needed for using this malloc on ANSI C/C++
++ systems, so long as you haven't changed compile-time options about
++ naming and tuning parameters. If you do, then you can create your
++ own malloc.h that does include all settings by cutting at the point
++ indicated below. Note that you may already by default be using a C
++ library containing a malloc that is based on some version of this
++ malloc (for example in linux). You might still want to use the one
++ in this file to customize settings or to avoid overheads associated
++ with library versions.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++* Vital statistics:
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Supported pointer/size_t representation: 4 or 8 bytes
++ size_t MUST be an unsigned type of the same width as
++ pointers. (If you are using an ancient system that declares
++ size_t as a signed type, or need it to be a different width
++ than pointers, you can use a previous release of this malloc
++ (e.g. 2.7.2) supporting these.)
+
++ Alignment: 8 bytes (default)
++ This suffices for nearly all current machines and C compilers.
++ However, you can define MALLOC_ALIGNMENT to be wider than this
++ if necessary (up to 128bytes), at the expense of using more space.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes)
++ 8 or 16 bytes (if 8byte sizes)
++ Each malloced chunk has a hidden word of overhead holding size
++ and status information, and additional cross-check word
++ if FOOTERS is defined.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead)
++ 8-byte ptrs: 32 bytes (including overhead)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Even a request for zero bytes (i.e., malloc(0)) returns a
++ pointer to something of the minimum allocatable size.
++ The maximum overhead wastage (i.e., number of extra bytes
++ allocated than were requested in malloc) is less than or equal
++ to the minimum size, except for requests >= mmap_threshold that
++ are serviced via mmap(), where the worst case wastage is about
++ 32 bytes plus the remainder from a system page (the minimal
++ mmap unit); typically 4096 or 8192 bytes.
+
++ Security: static-safe; optionally more or less
++ The "security" of malloc refers to the ability of malicious
++ code to accentuate the effects of errors (for example, freeing
++ space that is not currently malloc'ed or overwriting past the
++ ends of chunks) in code that calls malloc. This malloc
++ guarantees not to modify any memory locations below the base of
++ heap, i.e., static variables, even in the presence of usage
++ errors. The routines additionally detect most improper frees
++ and reallocs. All this holds as long as the static bookkeeping
++ for malloc itself is not corrupted by some other means. This
++ is only one aspect of security -- these checks do not, and
++ cannot, detect all possible programming errors.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ If FOOTERS is defined nonzero, then each allocated chunk
++ carries an additional check word to verify that it was malloced
++ from its space. These check words are the same within each
++ execution of a program using malloc, but differ across
++ executions, so externally crafted fake chunks cannot be
++ freed. This improves security by rejecting frees/reallocs that
++ could corrupt heap memory, in addition to the checks preventing
++ writes to statics that are always on. This may further improve
++ security at the expense of time and space overhead. (Note that
++ FOOTERS may also be worth using with MSPACES.)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ By default detected errors cause the program to abort (calling
++ "abort()"). You can override this to instead proceed past
++ errors by defining PROCEED_ON_ERROR. In this case, a bad free
++ has no effect, and a malloc that encounters a bad address
++ caused by user overwrites will ignore the bad address by
++ dropping pointers and indices to all known memory. This may
++ be appropriate for programs that should continue if at all
++ possible in the face of programming errors, although they may
++ run out of memory because dropped memory is never reclaimed.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ If you don't like either of these options, you can define
++ CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
++ else. And if if you are sure that your program using malloc has
++ no errors or vulnerabilities, you can define INSECURE to 1,
++ which might (or might not) provide a small performance improvement.
+
++ Thread-safety: NOT thread-safe unless USE_LOCKS defined
++ When USE_LOCKS is defined, each public call to malloc, free,
++ etc is surrounded with either a pthread mutex or a win32
++ spinlock (depending on WIN32). This is not especially fast, and
++ can be a major bottleneck. It is designed only to provide
++ minimal protection in concurrent environments, and to provide a
++ basis for extensions. If you are using malloc in a concurrent
++ program, consider instead using ptmalloc, which is derived from
++ a version of this malloc. (See http://www.malloc.de).
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
++ This malloc can use unix sbrk or any emulation (invoked using
++ the CALL_MORECORE macro) and/or mmap/munmap or any emulation
++ (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
++ memory. On most unix systems, it tends to work best if both
++ MORECORE and MMAP are enabled. On Win32, it uses emulations
++ based on VirtualAlloc. It also uses common C library functions
++ like memset.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Compliance: I believe it is compliant with the Single Unix Specification
++ (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
++ others as well.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++* Overview of algorithms
+
++ This is not the fastest, most space-conserving, most portable, or
++ most tunable malloc ever written. However it is among the fastest
++ while also being among the most space-conserving, portable and
++ tunable. Consistent balance across these factors results in a good
++ general-purpose allocator for malloc-intensive programs.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ In most ways, this malloc is a best-fit allocator. Generally, it
++ chooses the best-fitting existing chunk for a request, with ties
++ broken in approximately least-recently-used order. (This strategy
++ normally maintains low fragmentation.) However, for requests less
++ than 256bytes, it deviates from best-fit when there is not an
++ exactly fitting available chunk by preferring to use space adjacent
++ to that used for the previous small request, as well as by breaking
++ ties in approximately most-recently-used order. (These enhance
++ locality of series of small allocations.) And for very large requests
++ (>= 256Kb by default), it relies on system memory mapping
++ facilities, if supported. (This helps avoid carrying around and
++ possibly fragmenting memory used only for large chunks.)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ All operations (except malloc_stats and mallinfo) have execution
++ times that are bounded by a constant factor of the number of bits in
++ a size_t, not counting any clearing in calloc or copying in realloc,
++ or actions surrounding MORECORE and MMAP that have times
++ proportional to the number of non-contiguous regions returned by
++ system allocation routines, which is often just 1.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ The implementation is not very modular and seriously overuses
++ macros. Perhaps someday all C compilers will do as good a job
++ inlining modular code as can now be done by brute-force expansion,
++ but now, enough of them seem not to.
+
++ Some compilers issue a lot of warnings about code that is
++ dead/unreachable only on some platforms, and also about intentional
++ uses of negation on unsigned types. All known cases of each can be
++ ignored.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ For a longer but out of date high-level description, see
++ http://gee.cs.oswego.edu/dl/html/malloc.html
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++* MSPACES
++ If MSPACES is defined, then in addition to malloc, free, etc.,
++ this file also defines mspace_malloc, mspace_free, etc. These
++ are versions of malloc routines that take an "mspace" argument
++ obtained using create_mspace, to control all internal bookkeeping.
++ If ONLY_MSPACES is defined, only these versions are compiled.
++ So if you would like to use this allocator for only some allocations,
++ and your system malloc for others, you can compile with
++ ONLY_MSPACES and then do something like...
++ static mspace mymspace = create_mspace(0,0); // for example
++ #define mymalloc(bytes) mspace_malloc(mymspace, bytes)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ (Note: If you only need one instance of an mspace, you can instead
++ use "USE_DL_PREFIX" to relabel the global malloc.)
+
++ You can similarly create thread-local allocators by storing
++ mspaces as thread-locals. For example:
++ static __thread mspace tlms = 0;
++ void* tlmalloc(size_t bytes) {
++ if (tlms == 0) tlms = create_mspace(0, 0);
++ return mspace_malloc(tlms, bytes);
++ }
++ void tlfree(void* mem) { mspace_free(tlms, mem); }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Unless FOOTERS is defined, each mspace is completely independent.
++ You cannot allocate from one and free to another (although
++ conformance is only weakly checked, so usage errors are not always
++ caught). If FOOTERS is defined, then each chunk carries around a tag
++ indicating its originating mspace, and frees are directed to their
++ originating spaces.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ ------------------------- Compile-time options ---------------------------
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++Be careful in setting #define values for numerical constants of type
++size_t. On some systems, literal values are not automatically extended
++to size_t precision unless they are explicitly casted.
+
++WIN32 default: defined if _WIN32 defined
++ Defining WIN32 sets up defaults for MS environment and compilers.
++ Otherwise defaults are for unix.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++MALLOC_ALIGNMENT default: (size_t)8
++ Controls the minimum alignment for malloc'ed chunks. It must be a
++ power of two and at least 8, even on machines for which smaller
++ alignments would suffice. It may be defined as larger than this
++ though. Note however that code and data structures are optimized for
++ the case of 8-byte alignment.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++MSPACES default: 0 (false)
++ If true, compile in support for independent allocation spaces.
++ This is only supported if HAVE_MMAP is true.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ONLY_MSPACES default: 0 (false)
++ If true, only compile in mspace versions, not regular versions.
+
++USE_LOCKS default: 0 (false)
++ Causes each call to each public routine to be surrounded with
++ pthread or WIN32 mutex lock/unlock. (If set true, this can be
++ overridden on a per-mspace basis for mspace versions.)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++FOOTERS default: 0
++ If true, provide extra checking and dispatching by placing
++ information in the footers of allocated chunks. This adds
++ space and time overhead.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++INSECURE default: 0
++ If true, omit checks for usage errors and heap space overwrites.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++USE_DL_PREFIX default: NOT defined
++ Causes compiler to prefix all public routines with the string 'dl'.
++ This can be useful when you only want to use this malloc in one part
++ of a program, using your regular system malloc elsewhere.
+
++ABORT default: defined as abort()
++ Defines how to abort on failed checks. On most systems, a failed
++ check cannot die with an "assert" or even print an informative
++ message, because the underlying print routines in turn call malloc,
++ which will fail again. Generally, the best policy is to simply call
++ abort(). It's not very useful to do more than this because many
++ errors due to overwriting will show up as address faults (null, odd
++ addresses etc) rather than malloc-triggered checks, so will also
++ abort. Also, most compilers know that abort() does not return, so
++ can better optimize code conditionally calling it.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++PROCEED_ON_ERROR default: defined as 0 (false)
++ Controls whether detected bad addresses cause them to bypassed
++ rather than aborting. If set, detected bad arguments to free and
++ realloc are ignored. And all bookkeeping information is zeroed out
++ upon a detected overwrite of freed heap space, thus losing the
++ ability to ever return it from malloc again, but enabling the
++ application to proceed. If PROCEED_ON_ERROR is defined, the
++ static variable malloc_corruption_error_count is compiled in
++ and can be examined to see if errors have occurred. This option
++ generates slower code than the default abort policy.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++DEBUG default: NOT defined
++ The DEBUG setting is mainly intended for people trying to modify
++ this code or diagnose problems when porting to new platforms.
++ However, it may also be able to better isolate user errors than just
++ using runtime checks. The assertions in the check routines spell
++ out in more detail the assumptions and invariants underlying the
++ algorithms. The checking is fairly extensive, and will slow down
++ execution noticeably. Calling malloc_stats or mallinfo with DEBUG
++ set will attempt to check every non-mmapped allocated and free chunk
++ in the course of computing the summaries.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ABORT_ON_ASSERT_FAILURE default: defined as 1 (true)
++ Debugging assertion failures can be nearly impossible if your
++ version of the assert macro causes malloc to be called, which will
++ lead to a cascade of further failures, blowing the runtime stack.
++ ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
++ which will usually make debugging easier.
+
++MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32
++ The action to take before "return 0" when malloc fails to be able to
++ return memory because there is none available.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES
++ True if this system supports sbrk or an emulation of it.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++MORECORE default: sbrk
++ The name of the sbrk-style system routine to call to obtain more
++ memory. See below for guidance on writing custom MORECORE
++ functions. The type of the argument to sbrk/MORECORE varies across
++ systems. It cannot be size_t, because it supports negative
++ arguments, so it is normally the signed type of the same width as
++ size_t (sometimes declared as "intptr_t"). It doesn't much matter
++ though. Internally, we only call it with arguments less than half
++ the max value of a size_t, which should work across all reasonable
++ possibilities, although sometimes generating compiler warnings. See
++ near the end of this file for guidelines for creating a custom
++ version of MORECORE.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++MORECORE_CONTIGUOUS default: 1 (true)
++ If true, take advantage of fact that consecutive calls to MORECORE
++ with positive arguments always return contiguous increasing
++ addresses. This is true of unix sbrk. It does not hurt too much to
++ set it true anyway, since malloc copes with non-contiguities.
++ Setting it false when definitely non-contiguous saves time
++ and possibly wasted space it would take to discover this though.
+
++MORECORE_CANNOT_TRIM default: NOT defined
++ True if MORECORE cannot release space back to the system when given
++ negative arguments. This is generally necessary only if you are
++ using a hand-crafted MORECORE function that cannot handle negative
++ arguments.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++HAVE_MMAP default: 1 (true)
++ True if this system supports mmap or an emulation of it. If so, and
++ HAVE_MORECORE is not true, MMAP is used for all system
++ allocation. If set and HAVE_MORECORE is true as well, MMAP is
++ primarily used to directly allocate very large blocks. It is also
++ used as a backup strategy in cases where MORECORE fails to provide
++ space from system. Note: A single call to MUNMAP is assumed to be
++ able to unmap memory that may have be allocated using multiple calls
++ to MMAP, so long as they are adjacent.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++HAVE_MREMAP default: 1 on linux, else 0
++ If true realloc() uses mremap() to re-allocate large blocks and
++ extend or shrink allocation spaces.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++MMAP_CLEARS default: 1 on unix
++ True if mmap clears memory so calloc doesn't need to. This is true
++ for standard unix mmap using /dev/zero.
+
++USE_BUILTIN_FFS default: 0 (i.e., not used)
++ Causes malloc to use the builtin ffs() function to compute indices.
++ Some compilers may recognize and intrinsify ffs to be faster than the
++ supplied C version. Also, the case of x86 using gcc is special-cased
++ to an asm instruction, so is already as fast as it can be, and so
++ this setting has no effect. (On most x86s, the asm version is only
++ slightly faster than the C version.)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++malloc_getpagesize default: derive from system includes, or 4096.
++ The system page size. To the extent possible, this malloc manages
++ memory from the system in page-size units. This may be (and
++ usually is) a function rather than a constant. This is ignored
++ if WIN32, where page size is determined using getSystemInfo during
++ initialization.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++USE_DEV_RANDOM default: 0 (i.e., not used)
++ Causes malloc to use /dev/random to initialize secure magic seed for
++ stamping footers. Otherwise, the current time is used.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++NO_MALLINFO default: 0
++ If defined, don't compile "mallinfo". This can be a simple way
++ of dealing with mismatches between system declarations and
++ those in this file.
+
++MALLINFO_FIELD_TYPE default: size_t
++ The type of the fields in the mallinfo struct. This was originally
++ defined as "int" in SVID etc, but is more usefully defined as
++ size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++REALLOC_ZERO_BYTES_FREES default: not defined
++ This should be set if a call to realloc with zero bytes should
++ be the same as a call to free. Some people think it should. Otherwise,
++ since this malloc returns a unique pointer for malloc(0), so does
++ realloc(p, 0).
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
++LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H
++LACKS_STDLIB_H default: NOT defined unless on WIN32
++ Define these if your system does not have these header files.
++ You might need to manually insert some of the declarations they provide.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS,
++ system_info.dwAllocationGranularity in WIN32,
++ otherwise 64K.
++ Also settable using mallopt(M_GRANULARITY, x)
++ The unit for allocating and deallocating memory from the system. On
++ most systems with contiguous MORECORE, there is no reason to
++ make this more than a page. However, systems with MMAP tend to
++ either require or encourage larger granularities. You can increase
++ this value to prevent system allocation functions to be called so
++ often, especially if they are slow. The value must be at least one
++ page and must be a power of two. Setting to 0 causes initialization
++ to either page size or win32 region size. (Note: In previous
++ versions of malloc, the equivalent of this option was called
++ "TOP_PAD")
+
++DEFAULT_TRIM_THRESHOLD default: 2MB
++ Also settable using mallopt(M_TRIM_THRESHOLD, x)
++ The maximum amount of unused top-most memory to keep before
++ releasing via malloc_trim in free(). Automatic trimming is mainly
++ useful in long-lived programs using contiguous MORECORE. Because
++ trimming via sbrk can be slow on some systems, and can sometimes be
++ wasteful (in cases where programs immediately afterward allocate
++ more large chunks) the value should be high enough so that your
++ overall system performance would improve by releasing this much
++ memory. As a rough guide, you might set to a value close to the
++ average size of a process (program) running on your system.
++ Releasing this much memory would allow such a process to run in
++ memory. Generally, it is worth tuning trim thresholds when a
++ program undergoes phases where several large chunks are allocated
++ and released in ways that can reuse each other's storage, perhaps
++ mixed with phases where there are no such chunks at all. The trim
++ value must be greater than page size to have any useful effect. To
++ disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
++ some people use of mallocing a huge space and then freeing it at
++ program startup, in an attempt to reserve system memory, doesn't
++ have the intended effect under automatic trimming, since that memory
++ will immediately be returned to the system.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++DEFAULT_MMAP_THRESHOLD default: 256K
++ Also settable using mallopt(M_MMAP_THRESHOLD, x)
++ The request size threshold for using MMAP to directly service a
++ request. Requests of at least this size that cannot be allocated
++ using already-existing space will be serviced via mmap. (If enough
++ normal freed space already exists it is used instead.) Using mmap
++ segregates relatively large chunks of memory so that they can be
++ individually obtained and released from the host system. A request
++ serviced through mmap is never reused by any other request (at least
++ not directly; the system may just so happen to remap successive
++ requests to the same locations). Segregating space in this way has
++ the benefits that: Mmapped space can always be individually released
++ back to the system, which helps keep the system level memory demands
++ of a long-lived program low. Also, mapped memory doesn't become
++ `locked' between other chunks, as can happen with normally allocated
++ chunks, which means that even trimming via malloc_trim would not
++ release them. However, it has the disadvantage that the space
++ cannot be reclaimed, consolidated, and then used to service later
++ requests, as happens with normal chunks. The advantages of mmap
++ nearly always outweigh disadvantages for "large" chunks, but the
++ value of "large" may vary across systems. The default is an
++ empirically derived value that works well in most systems. You can
++ disable mmap by setting to MAX_SIZE_T.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++*/
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifndef WIN32
++#ifdef _WIN32
++#define WIN32 1
++#endif /* _WIN32 */
++#endif /* WIN32 */
++#ifdef WIN32
++#define WIN32_LEAN_AND_MEAN
++#include
++#define HAVE_MMAP 1
++#define HAVE_MORECORE 0
++#define LACKS_UNISTD_H
++#define LACKS_SYS_PARAM_H
++#define LACKS_SYS_MMAN_H
++#define LACKS_STRING_H
++#define LACKS_STRINGS_H
++#define LACKS_SYS_TYPES_H
++#define LACKS_ERRNO_H
++#define MALLOC_FAILURE_ACTION
++#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
++#endif /* WIN32 */
+
++#ifdef __OS2__
++#define INCL_DOS
++#include
++#define HAVE_MMAP 1
++#define HAVE_MORECORE 0
++#define LACKS_SYS_MMAN_H
++#endif /* __OS2__ */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if defined(DARWIN) || defined(_DARWIN)
++/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
++#ifndef HAVE_MORECORE
++#define HAVE_MORECORE 0
++#define HAVE_MMAP 1
++#endif /* HAVE_MORECORE */
++#endif /* DARWIN */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#ifndef LACKS_SYS_TYPES_H
++#include /* For size_t */
++#endif /* LACKS_SYS_TYPES_H */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* The maximum possible size_t value has all bits set */
++#define MAX_SIZE_T (~(size_t)0)
+
++#ifndef ONLY_MSPACES
++#define ONLY_MSPACES 0
++#endif /* ONLY_MSPACES */
++#ifndef MSPACES
++#if ONLY_MSPACES
++#define MSPACES 1
++#else /* ONLY_MSPACES */
++#define MSPACES 0
++#endif /* ONLY_MSPACES */
++#endif /* MSPACES */
++#ifndef MALLOC_ALIGNMENT
++#define MALLOC_ALIGNMENT ((size_t)8U)
++#endif /* MALLOC_ALIGNMENT */
++#ifndef FOOTERS
++#define FOOTERS 0
++#endif /* FOOTERS */
++#ifndef ABORT
++#define ABORT abort()
++#endif /* ABORT */
++#ifndef ABORT_ON_ASSERT_FAILURE
++#define ABORT_ON_ASSERT_FAILURE 1
++#endif /* ABORT_ON_ASSERT_FAILURE */
++#ifndef PROCEED_ON_ERROR
++#define PROCEED_ON_ERROR 0
++#endif /* PROCEED_ON_ERROR */
++#ifndef USE_LOCKS
++#define USE_LOCKS 0
++#endif /* USE_LOCKS */
++#ifndef INSECURE
++#define INSECURE 0
++#endif /* INSECURE */
++#ifndef HAVE_MMAP
++#define HAVE_MMAP 1
++#endif /* HAVE_MMAP */
++#ifndef MMAP_CLEARS
++#define MMAP_CLEARS 1
++#endif /* MMAP_CLEARS */
++#ifndef HAVE_MREMAP
++#ifdef linux
++#define HAVE_MREMAP 1
++#else /* linux */
++#define HAVE_MREMAP 0
++#endif /* linux */
++#endif /* HAVE_MREMAP */
++#ifndef MALLOC_FAILURE_ACTION
++#define MALLOC_FAILURE_ACTION errno = ENOMEM;
++#endif /* MALLOC_FAILURE_ACTION */
++#ifndef HAVE_MORECORE
++#if ONLY_MSPACES
++#define HAVE_MORECORE 0
++#else /* ONLY_MSPACES */
++#define HAVE_MORECORE 1
++#endif /* ONLY_MSPACES */
++#endif /* HAVE_MORECORE */
++#if !HAVE_MORECORE
++#define MORECORE_CONTIGUOUS 0
++#else /* !HAVE_MORECORE */
++#ifndef MORECORE
++#define MORECORE sbrk
++#endif /* MORECORE */
++#ifndef MORECORE_CONTIGUOUS
++#define MORECORE_CONTIGUOUS 1
++#endif /* MORECORE_CONTIGUOUS */
++#endif /* HAVE_MORECORE */
++#ifndef DEFAULT_GRANULARITY
++#if MORECORE_CONTIGUOUS
++#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */
++#else /* MORECORE_CONTIGUOUS */
++#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
++#endif /* MORECORE_CONTIGUOUS */
++#endif /* DEFAULT_GRANULARITY */
++#ifndef DEFAULT_TRIM_THRESHOLD
++#ifndef MORECORE_CANNOT_TRIM
++#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
++#else /* MORECORE_CANNOT_TRIM */
++#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
++#endif /* MORECORE_CANNOT_TRIM */
++#endif /* DEFAULT_TRIM_THRESHOLD */
++#ifndef DEFAULT_MMAP_THRESHOLD
++#if HAVE_MMAP
++#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
++#else /* HAVE_MMAP */
++#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
++#endif /* HAVE_MMAP */
++#endif /* DEFAULT_MMAP_THRESHOLD */
++#ifndef USE_BUILTIN_FFS
++#define USE_BUILTIN_FFS 0
++#endif /* USE_BUILTIN_FFS */
++#ifndef USE_DEV_RANDOM
++#define USE_DEV_RANDOM 0
++#endif /* USE_DEV_RANDOM */
++#ifndef NO_MALLINFO
++#define NO_MALLINFO 0
++#endif /* NO_MALLINFO */
++#ifndef MALLINFO_FIELD_TYPE
++#define MALLINFO_FIELD_TYPE size_t
++#endif /* MALLINFO_FIELD_TYPE */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ mallopt tuning options. SVID/XPG defines four standard parameter
++ numbers for mallopt, normally defined in malloc.h. None of these
++ are used in this malloc, so setting them has no effect. But this
++ malloc does support the following options.
++*/
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define M_TRIM_THRESHOLD (-1)
++#define M_GRANULARITY (-2)
++#define M_MMAP_THRESHOLD (-3)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* ------------------------ Mallinfo declarations ------------------------ */
+
++#if !NO_MALLINFO
++/*
++ This version of malloc supports the standard SVID/XPG mallinfo
++ routine that returns a struct containing usage properties and
++ statistics. It should work on any system that has a
++ /usr/include/malloc.h defining struct mallinfo. The main
++ declaration needed is the mallinfo struct that is returned (by-copy)
++ by mallinfo(). The malloinfo struct contains a bunch of fields that
++ are not even meaningful in this version of malloc. These fields are
++ are instead filled by mallinfo() with other numbers that might be of
++ interest.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
++ /usr/include/malloc.h file that includes a declaration of struct
++ mallinfo. If so, it is included; else a compliant version is
++ declared below. These must be precisely the same for mallinfo() to
++ work. The original SVID version of this struct, defined on most
++ systems with mallinfo, declares all fields as ints. But some others
++ define as unsigned long. If your system defines the fields using a
++ type of different width than listed here, you MUST #include your
++ system version and #define HAVE_USR_INCLUDE_MALLOC_H.
++*/
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* #define HAVE_USR_INCLUDE_MALLOC_H */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef HAVE_USR_INCLUDE_MALLOC_H
++#include "/usr/include/malloc.h"
++#else /* HAVE_USR_INCLUDE_MALLOC_H */
+
++/* HP-UX's stdlib.h redefines mallinfo unless _STRUCT_MALLINFO is defined */
++#define _STRUCT_MALLINFO
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++struct mallinfo {
++ MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
++ MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
++ MALLINFO_FIELD_TYPE smblks; /* always 0 */
++ MALLINFO_FIELD_TYPE hblks; /* always 0 */
++ MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
++ MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
++ MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
++ MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
++ MALLINFO_FIELD_TYPE fordblks; /* total free space */
++ MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
++};
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#endif /* HAVE_USR_INCLUDE_MALLOC_H */
++#endif /* NO_MALLINFO */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
+
++#if !ONLY_MSPACES
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ------------------- Declarations of public routines ------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#ifndef USE_DL_PREFIX
++#define dlcalloc calloc
++#define dlfree free
++#define dlmalloc malloc
++#define dlmemalign memalign
++#define dlrealloc realloc
++#define dlvalloc valloc
++#define dlpvalloc pvalloc
++#define dlmallinfo mallinfo
++#define dlmallopt mallopt
++#define dlmalloc_trim malloc_trim
++#define dlmalloc_stats malloc_stats
++#define dlmalloc_usable_size malloc_usable_size
++#define dlmalloc_footprint malloc_footprint
++#define dlmalloc_max_footprint malloc_max_footprint
++#define dlindependent_calloc independent_calloc
++#define dlindependent_comalloc independent_comalloc
++#endif /* USE_DL_PREFIX */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++/*
++ malloc(size_t n)
++ Returns a pointer to a newly allocated chunk of at least n bytes, or
++ null if no space is available, in which case errno is set to ENOMEM
++ on ANSI C systems.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ If n is zero, malloc returns a minimum-sized chunk. (The minimum
++ size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
++ systems.) Note that size_t is an unsigned type, so calls with
++ arguments that would be negative if signed are interpreted as
++ requests for huge amounts of space, which will often fail. The
++ maximum supported value of n differs across systems, but is in all
++ cases less than the maximum representable value of a size_t.
++*/
++void* dlmalloc(size_t);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ free(void* p)
++ Releases the chunk of memory pointed to by p, that had been previously
++ allocated using malloc or a related routine such as realloc.
++ It has no effect if p is null. If p was not malloced or already
++ freed, free(p) will by default cause the current program to abort.
++*/
++void dlfree(void*);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ calloc(size_t n_elements, size_t element_size);
++ Returns a pointer to n_elements * element_size bytes, with all locations
++ set to zero.
++*/
++void* dlcalloc(size_t, size_t);
+
++/*
++ realloc(void* p, size_t n)
++ Returns a pointer to a chunk of size n that contains the same data
++ as does chunk p up to the minimum of (n, p's size) bytes, or null
++ if no space is available.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ The returned pointer may or may not be the same as p. The algorithm
++ prefers extending p in most cases when possible, otherwise it
++ employs the equivalent of a malloc-copy-free sequence.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ If p is null, realloc is equivalent to malloc.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ If space is not available, realloc returns null, errno is set (if on
++ ANSI) and p is NOT freed.
+
++ if n is for fewer bytes than already held by p, the newly unused
++ space is lopped off and freed if possible. realloc with a size
++ argument of zero (re)allocates a minimum-sized chunk.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ The old unix realloc convention of allowing the last-free'd chunk
++ to be used as an argument to realloc is not supported.
++*/
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++void* dlrealloc(void*, size_t);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ memalign(size_t alignment, size_t n);
++ Returns a pointer to a newly allocated chunk of n bytes, aligned
++ in accord with the alignment argument.
+
++ The alignment argument should be a power of two. If the argument is
++ not a power of two, the nearest greater power is used.
++ 8-byte alignment is guaranteed by normal malloc calls, so don't
++ bother calling memalign with an argument of 8 or less.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Overreliance on memalign is a sure way to fragment space.
++*/
++void* dlmemalign(size_t, size_t);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ valloc(size_t n);
++ Equivalent to memalign(pagesize, n), where pagesize is the page
++ size of the system. If the pagesize is unknown, 4096 is used.
++*/
++void* dlvalloc(size_t);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ mallopt(int parameter_number, int parameter_value)
++ Sets tunable parameters The format is to provide a
++ (parameter-number, parameter-value) pair. mallopt then sets the
++ corresponding parameter to the argument value if it can (i.e., so
++ long as the value is meaningful), and returns 1 if successful else
++ 0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
++ normally defined in malloc.h. None of these are use in this malloc,
++ so setting them has no effect. But this malloc also supports other
++ options in mallopt. See below for details. Briefly, supported
++ parameters are as follows (listed defaults are for "typical"
++ configurations).
+
++ Symbol param # default allowed param values
++ M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables)
++ M_GRANULARITY -2 page size any power of 2 >= page size
++ M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
++*/
++int dlmallopt(int, int);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ malloc_footprint();
++ Returns the number of bytes obtained from the system. The total
++ number of bytes allocated by malloc, realloc etc., is less than this
++ value. Unlike mallinfo, this function returns only a precomputed
++ result, so can be called frequently to monitor memory consumption.
++ Even if locks are otherwise defined, this function does not use them,
++ so results might not be up to date.
++*/
++size_t dlmalloc_footprint(void);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ malloc_max_footprint();
++ Returns the maximum number of bytes obtained from the system. This
++ value will be greater than current footprint if deallocated space
++ has been reclaimed by the system. The peak number of bytes allocated
++ by malloc, realloc etc., is less than this value. Unlike mallinfo,
++ this function returns only a precomputed result, so can be called
++ frequently to monitor memory consumption. Even if locks are
++ otherwise defined, this function does not use them, so results might
++ not be up to date.
++*/
++size_t dlmalloc_max_footprint(void);
+
++#if !NO_MALLINFO
++/*
++ mallinfo()
++ Returns (by copy) a struct containing various summary statistics:
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ arena: current total non-mmapped bytes allocated from system
++ ordblks: the number of free chunks
++ smblks: always zero.
++ hblks: current number of mmapped regions
++ hblkhd: total bytes held in mmapped regions
++ usmblks: the maximum total allocated space. This will be greater
++ than current total if trimming has occurred.
++ fsmblks: always zero
++ uordblks: current total allocated space (normal or mmapped)
++ fordblks: total free space
++ keepcost: the maximum number of bytes that could ideally be released
++ back to system via malloc_trim. ("ideally" means that
++ it ignores page restrictions etc.)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Because these fields are ints, but internal bookkeeping may
++ be kept as longs, the reported values may wrap around zero and
++ thus be inaccurate.
++*/
++struct mallinfo dlmallinfo(void);
++#endif /* NO_MALLINFO */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
+
++ independent_calloc is similar to calloc, but instead of returning a
++ single cleared space, it returns an array of pointers to n_elements
++ independent elements that can hold contents of size elem_size, each
++ of which starts out cleared, and can be independently freed,
++ realloc'ed etc. The elements are guaranteed to be adjacently
++ allocated (this is not guaranteed to occur with multiple callocs or
++ mallocs), which may also improve cache locality in some
++ applications.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ The "chunks" argument is optional (i.e., may be null, which is
++ probably the most typical usage). If it is null, the returned array
++ is itself dynamically allocated and should also be freed when it is
++ no longer needed. Otherwise, the chunks array must be of at least
++ n_elements in length. It is filled in with the pointers to the
++ chunks.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ In either case, independent_calloc returns this pointer array, or
++ null if the allocation failed. If n_elements is zero and "chunks"
++ is null, it returns a chunk representing an array with zero elements
++ (which should be freed if not wanted).
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Each element must be individually freed when it is no longer
++ needed. If you'd like to instead be able to free all at once, you
++ should instead use regular calloc and assign pointers into this
++ space to represent elements. (In this case though, you cannot
++ independently free elements.)
+
++ independent_calloc simplifies and speeds up implementations of many
++ kinds of pools. It may also be useful when constructing large data
++ structures that initially have a fixed number of fixed-sized nodes,
++ but the number is not known at compile time, and some of the nodes
++ may later need to be freed. For example:
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ struct Node { int item; struct Node* next; };
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ struct Node* build_list() {
++ struct Node** pool;
++ int n = read_number_of_nodes_needed();
++ if (n <= 0) return 0;
++ pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
++ if (pool == 0) die();
++ // organize into a linked list...
++ struct Node* first = pool[0];
++ for (i = 0; i < n-1; ++i)
++ pool[i]->next = pool[i+1];
++ free(pool); // Can now free the array (or not, if it is needed later)
++ return first;
++ }
++*/
++void** dlindependent_calloc(size_t, size_t, void**);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
+
++ independent_comalloc allocates, all at once, a set of n_elements
++ chunks with sizes indicated in the "sizes" array. It returns
++ an array of pointers to these elements, each of which can be
++ independently freed, realloc'ed etc. The elements are guaranteed to
++ be adjacently allocated (this is not guaranteed to occur with
++ multiple callocs or mallocs), which may also improve cache locality
++ in some applications.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ The "chunks" argument is optional (i.e., may be null). If it is null
++ the returned array is itself dynamically allocated and should also
++ be freed when it is no longer needed. Otherwise, the chunks array
++ must be of at least n_elements in length. It is filled in with the
++ pointers to the chunks.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ In either case, independent_comalloc returns this pointer array, or
++ null if the allocation failed. If n_elements is zero and chunks is
++ null, it returns a chunk representing an array with zero elements
++ (which should be freed if not wanted).
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Each element must be individually freed when it is no longer
++ needed. If you'd like to instead be able to free all at once, you
++ should instead use a single regular malloc, and assign pointers at
++ particular offsets in the aggregate space. (In this case though, you
++ cannot independently free elements.)
+
++ independent_comallac differs from independent_calloc in that each
++ element may have a different size, and also that it does not
++ automatically clear elements.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ independent_comalloc can be used to speed up allocation in cases
++ where several structs or objects must always be allocated at the
++ same time. For example:
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ struct Head { ... }
++ struct Foot { ... }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ void send_message(char* msg) {
++ int msglen = strlen(msg);
++ size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
++ void* chunks[3];
++ if (independent_comalloc(3, sizes, chunks) == 0)
++ die();
++ struct Head* head = (struct Head*)(chunks[0]);
++ char* body = (char*)(chunks[1]);
++ struct Foot* foot = (struct Foot*)(chunks[2]);
++ // ...
++ }
+
++ In general though, independent_comalloc is worth using only for
++ larger values of n_elements. For small values, you probably won't
++ detect enough difference from series of malloc calls to bother.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Overuse of independent_comalloc can increase overall memory usage,
++ since it cannot reuse existing noncontiguous small chunks that
++ might be available for some of the elements.
++*/
++void** dlindependent_comalloc(size_t, size_t*, void**);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ pvalloc(size_t n);
++ Equivalent to valloc(minimum-page-that-holds(n)), that is,
++ round up n to nearest pagesize.
++ */
++void* dlpvalloc(size_t);
+
++/*
++ malloc_trim(size_t pad);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ If possible, gives memory back to the system (via negative arguments
++ to sbrk) if there is unused memory at the `high' end of the malloc
++ pool or in unused MMAP segments. You can call this after freeing
++ large blocks of memory to potentially reduce the system-level memory
++ requirements of a program. However, it cannot guarantee to reduce
++ memory. Under some allocation patterns, some large free blocks of
++ memory will be locked between two used chunks, so they cannot be
++ given back to the system.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ The `pad' argument to malloc_trim represents the amount of free
++ trailing space to leave untrimmed. If this argument is zero, only
++ the minimum amount of memory to maintain internal data structures
++ will be left. Non-zero arguments can be supplied to maintain enough
++ trailing space to service future expected allocations without having
++ to re-obtain memory from the system.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Malloc_trim returns 1 if it actually released any memory, else 0.
++*/
++int dlmalloc_trim(size_t);
+
++/*
++ malloc_usable_size(void* p);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Returns the number of bytes you can actually use in
++ an allocated chunk, which may be more than you requested (although
++ often not) due to alignment and minimum size constraints.
++ You can use this many bytes without worrying about
++ overwriting other allocated objects. This is not a particularly great
++ programming practice. malloc_usable_size can be more useful in
++ debugging and assertions, for example:
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ p = malloc(n);
++ assert(malloc_usable_size(p) >= 256);
++*/
++size_t dlmalloc_usable_size(void*);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ malloc_stats();
++ Prints on stderr the amount of space obtained from the system (both
++ via sbrk and mmap), the maximum amount (which may be more than
++ current if malloc_trim and/or munmap got called), and the current
++ number of bytes allocated via malloc (or realloc, etc) but not yet
++ freed. Note that this is the number of bytes allocated, not the
++ number requested. It will be larger than the number requested
++ because of alignment and bookkeeping overhead. Because it includes
++ alignment wastage as being in use, this figure may be greater than
++ zero even when no user-level chunks are allocated.
+
++ The reported current and maximum system memory can be inaccurate if
++ a program makes other calls to system memory allocation functions
++ (normally sbrk) outside of malloc.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ malloc_stats prints only the most commonly interesting statistics.
++ More information can be obtained by calling mallinfo.
++*/
++void dlmalloc_stats(void);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#endif /* ONLY_MSPACES */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if MSPACES
+
++/*
++ mspace is an opaque type representing an independent
++ region of space that supports mspace_malloc, etc.
++*/
++typedef void* mspace;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ create_mspace creates and returns a new independent space with the
++ given initial capacity, or, if 0, the default granularity size. It
++ returns null if there is no system memory available to create the
++ space. If argument locked is non-zero, the space uses a separate
++ lock to control access. The capacity of the space will grow
++ dynamically as needed to service mspace_malloc requests. You can
++ control the sizes of incremental increases of this space by
++ compiling with a different DEFAULT_GRANULARITY or dynamically
++ setting with mallopt(M_GRANULARITY, value).
++*/
++mspace create_mspace(size_t capacity, int locked);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ destroy_mspace destroys the given space, and attempts to return all
++ of its memory back to the system, returning the total number of
++ bytes freed. After destruction, the results of access to all memory
++ used by the space become undefined.
++*/
++size_t destroy_mspace(mspace msp);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ create_mspace_with_base uses the memory supplied as the initial base
++ of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
++ space is used for bookkeeping, so the capacity must be at least this
++ large. (Otherwise 0 is returned.) When this initial space is
++ exhausted, additional memory will be obtained from the system.
++ Destroying this space will deallocate all additionally allocated
++ space (if possible) but not the initial base.
++*/
++mspace create_mspace_with_base(void* base, size_t capacity, int locked);
+
++/*
++ mspace_malloc behaves as malloc, but operates within
++ the given space.
++*/
++void* mspace_malloc(mspace msp, size_t bytes);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ mspace_free behaves as free, but operates within
++ the given space.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ If compiled with FOOTERS==1, mspace_free is not actually needed.
++ free may be called instead of mspace_free because freed chunks from
++ any space are handled by their originating spaces.
++*/
++void mspace_free(mspace msp, void* mem);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ mspace_realloc behaves as realloc, but operates within
++ the given space.
+
++ If compiled with FOOTERS==1, mspace_realloc is not actually
++ needed. realloc may be called instead of mspace_realloc because
++ realloced chunks from any space are handled by their originating
++ spaces.
++*/
++void* mspace_realloc(mspace msp, void* mem, size_t newsize);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ mspace_calloc behaves as calloc, but operates within
++ the given space.
++*/
++void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ mspace_memalign behaves as memalign, but operates within
++ the given space.
++*/
++void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ mspace_independent_calloc behaves as independent_calloc, but
++ operates within the given space.
++*/
++void** mspace_independent_calloc(mspace msp, size_t n_elements,
++ size_t elem_size, void* chunks[]);
+
++/*
++ mspace_independent_comalloc behaves as independent_comalloc, but
++ operates within the given space.
++*/
++void** mspace_independent_comalloc(mspace msp, size_t n_elements,
++ size_t sizes[], void* chunks[]);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ mspace_footprint() returns the number of bytes obtained from the
++ system for this space.
++*/
++size_t mspace_footprint(mspace msp);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ mspace_max_footprint() returns the peak number of bytes obtained from the
++ system for this space.
++*/
++size_t mspace_max_footprint(mspace msp);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++#if !NO_MALLINFO
++/*
++ mspace_mallinfo behaves as mallinfo, but reports properties of
++ the given space.
++*/
++struct mallinfo mspace_mallinfo(mspace msp);
++#endif /* NO_MALLINFO */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ mspace_malloc_stats behaves as malloc_stats, but reports
++ properties of the given space.
++*/
++void mspace_malloc_stats(mspace msp);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ mspace_trim behaves as malloc_trim, but
++ operates within the given space.
++*/
++int mspace_trim(mspace msp, size_t pad);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ An alias for mallopt.
++*/
++int mspace_mallopt(int, int);
+
++#endif /* MSPACES */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifdef __cplusplus
++}; /* end of extern "C" */
++#endif /* __cplusplus */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ ========================================================================
++ To make a fully customizable malloc.h header file, cut everything
++ above this line, put into file malloc.h, edit to suit, and #include it
++ on the next line, as well as in programs that use this malloc.
++ ========================================================================
++*/
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* #include "malloc.h" */
+
++/*------------------------------ internal #includes ---------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifdef _MSC_VER
++#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
++#endif /* _MSC_VER */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#include /* for printing in malloc_stats */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#ifndef LACKS_ERRNO_H
++#include /* for MALLOC_FAILURE_ACTION */
++#endif /* LACKS_ERRNO_H */
++#if FOOTERS
++#include /* for magic initialization */
++#endif /* FOOTERS */
++#ifndef LACKS_STDLIB_H
++#include /* for abort() */
++#endif /* LACKS_STDLIB_H */
++#ifdef DEBUG
++#if ABORT_ON_ASSERT_FAILURE
++#define assert(x) if(!(x)) ABORT
++#else /* ABORT_ON_ASSERT_FAILURE */
++#include
++#endif /* ABORT_ON_ASSERT_FAILURE */
++#else /* DEBUG */
++#define assert(x)
++#endif /* DEBUG */
++#ifndef LACKS_STRING_H
++#include /* for memset etc */
++#endif /* LACKS_STRING_H */
++#if USE_BUILTIN_FFS
++#ifndef LACKS_STRINGS_H
++#include /* for ffs */
++#endif /* LACKS_STRINGS_H */
++#endif /* USE_BUILTIN_FFS */
++#if HAVE_MMAP
++#ifndef LACKS_SYS_MMAN_H
++#include /* for mmap */
++#endif /* LACKS_SYS_MMAN_H */
++#ifndef LACKS_FCNTL_H
++#include
++#endif /* LACKS_FCNTL_H */
++#endif /* HAVE_MMAP */
++#if HAVE_MORECORE
++#ifndef LACKS_UNISTD_H
++#include /* for sbrk */
++#else /* LACKS_UNISTD_H */
++#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
++extern void* sbrk(ptrdiff_t);
++#endif /* FreeBSD etc */
++#endif /* LACKS_UNISTD_H */
++#endif /* HAVE_MMAP */
+
++#ifndef WIN32
++#ifndef malloc_getpagesize
++# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
++# ifndef _SC_PAGE_SIZE
++# define _SC_PAGE_SIZE _SC_PAGESIZE
++# endif
++# endif
++# ifdef _SC_PAGE_SIZE
++# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
++# else
++# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
++ extern size_t getpagesize();
++# define malloc_getpagesize getpagesize()
++# else
++# ifdef WIN32 /* use supplied emulation of getpagesize */
++# define malloc_getpagesize getpagesize()
++# else
++# ifndef LACKS_SYS_PARAM_H
++# include
++# endif
++# ifdef EXEC_PAGESIZE
++# define malloc_getpagesize EXEC_PAGESIZE
++# else
++# ifdef NBPG
++# ifndef CLSIZE
++# define malloc_getpagesize NBPG
++# else
++# define malloc_getpagesize (NBPG * CLSIZE)
++# endif
++# else
++# ifdef NBPC
++# define malloc_getpagesize NBPC
++# else
++# ifdef PAGESIZE
++# define malloc_getpagesize PAGESIZE
++# else /* just guess */
++# define malloc_getpagesize ((size_t)4096U)
++# endif
++# endif
++# endif
++# endif
++# endif
++# endif
++# endif
++#endif
++#endif
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ------------------- size_t and alignment properties -------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* The byte and bit size of a size_t */
++#define SIZE_T_SIZE (sizeof(size_t))
++#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Some constants coerced to size_t */
++/* Annoying but necessary to avoid errors on some platforms */
++#define SIZE_T_ZERO ((size_t)0)
++#define SIZE_T_ONE ((size_t)1)
++#define SIZE_T_TWO ((size_t)2)
++#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
++#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
++#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
++#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
+
++/* The bit mask value corresponding to MALLOC_ALIGNMENT */
++#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* True if address a has acceptable alignment */
++#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* the number of bytes to offset an address to align it */
++#define align_offset(A)\
++ ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
++ ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* -------------------------- MMAP preliminaries ------------------------- */
+
++/*
++ If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
++ checks to fail so compiler optimizer can delete code rather than
++ using so many "#if"s.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* MORECORE and MMAP must return MFAIL on failure */
++#define MFAIL ((void*)(MAX_SIZE_T))
++#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if !HAVE_MMAP
++#define IS_MMAPPED_BIT (SIZE_T_ZERO)
++#define USE_MMAP_BIT (SIZE_T_ZERO)
++#define CALL_MMAP(s) MFAIL
++#define CALL_MUNMAP(a, s) (-1)
++#define DIRECT_MMAP(s) MFAIL
+
++#else /* HAVE_MMAP */
++#define IS_MMAPPED_BIT (SIZE_T_ONE)
++#define USE_MMAP_BIT (SIZE_T_ONE)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if !defined(WIN32) && !defined (__OS2__)
++#define CALL_MUNMAP(a, s) munmap((a), (s))
++#define MMAP_PROT (PROT_READ|PROT_WRITE)
++#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
++#define MAP_ANONYMOUS MAP_ANON
++#endif /* MAP_ANON */
++#ifdef MAP_ANONYMOUS
++#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
++#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
++#else /* MAP_ANONYMOUS */
++/*
++ Nearly all versions of mmap support MAP_ANONYMOUS, so the following
++ is unlikely to be needed, but is supplied just in case.
++*/
++#define MMAP_FLAGS (MAP_PRIVATE)
++static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
++#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
++ (dev_zero_fd = open("/dev/zero", O_RDWR), \
++ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
++ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
++#endif /* MAP_ANONYMOUS */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define DIRECT_MMAP(s) CALL_MMAP(s)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#elif defined(__OS2__)
+
++/* OS/2 MMAP via DosAllocMem */
++static void* os2mmap(size_t size) {
++ void* ptr;
++ if (DosAllocMem(&ptr, size, OBJ_ANY|PAG_COMMIT|PAG_READ|PAG_WRITE) &&
++ DosAllocMem(&ptr, size, PAG_COMMIT|PAG_READ|PAG_WRITE))
++ return MFAIL;
++ return ptr;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define os2direct_mmap(n) os2mmap(n)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* This function supports releasing coalesed segments */
++static int os2munmap(void* ptr, size_t size) {
++ while (size) {
++ ULONG ulSize = size;
++ ULONG ulFlags = 0;
++ if (DosQueryMem(ptr, &ulSize, &ulFlags) != 0)
++ return -1;
++ if ((ulFlags & PAG_BASE) == 0 ||(ulFlags & PAG_COMMIT) == 0 ||
++ ulSize > size)
++ return -1;
++ if (DosFreeMem(ptr) != 0)
++ return -1;
++ ptr = ( void * ) ( ( char * ) ptr + ulSize );
++ size -= ulSize;
++ }
++ return 0;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define CALL_MMAP(s) os2mmap(s)
++#define CALL_MUNMAP(a, s) os2munmap((a), (s))
++#define DIRECT_MMAP(s) os2direct_mmap(s)
+
++#else /* WIN32 */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Win32 MMAP via VirtualAlloc */
++static void* win32mmap(size_t size) {
++ void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
++ return (ptr != 0)? ptr: MFAIL;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
++static void* win32direct_mmap(size_t size) {
++ void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
++ PAGE_EXECUTE_READWRITE);
++ return (ptr != 0)? ptr: MFAIL;
++}
+
++/* This function supports releasing coalesed segments */
++static int win32munmap(void* ptr, size_t size) {
++ MEMORY_BASIC_INFORMATION minfo;
++ char* cptr = ptr;
++ while (size) {
++ if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
++ return -1;
++ if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
++ minfo.State != MEM_COMMIT || minfo.RegionSize > size)
++ return -1;
++ if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
++ return -1;
++ cptr += minfo.RegionSize;
++ size -= minfo.RegionSize;
++ }
++ return 0;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define CALL_MMAP(s) win32mmap(s)
++#define CALL_MUNMAP(a, s) win32munmap((a), (s))
++#define DIRECT_MMAP(s) win32direct_mmap(s)
++#endif /* WIN32 */
++#endif /* HAVE_MMAP */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if HAVE_MMAP && HAVE_MREMAP
++#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
++#else /* HAVE_MMAP && HAVE_MREMAP */
++#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
++#endif /* HAVE_MMAP && HAVE_MREMAP */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if HAVE_MORECORE
++#define CALL_MORECORE(S) MORECORE(S)
++#else /* HAVE_MORECORE */
++#define CALL_MORECORE(S) MFAIL
++#endif /* HAVE_MORECORE */
+
++/* mstate bit set if contiguous morecore disabled or failed */
++#define USE_NONCONTIGUOUS_BIT (4U)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* segment bit set in create_mspace_with_base */
++#define EXTERN_BIT (8U)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* --------------------------- Lock preliminaries ------------------------ */
+
++#if USE_LOCKS
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ When locks are defined, there are up to two global locks:
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
++ MORECORE. In many cases sys_alloc requires two calls, that should
++ not be interleaved with calls by other threads. This does not
++ protect against direct calls to MORECORE by other threads not
++ using this lock, so there is still code to cope the best we can on
++ interference.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ * magic_init_mutex ensures that mparams.magic and other
++ unique mparams values are initialized only once.
++*/
+
++#if !defined(WIN32) && !defined(__OS2__)
++/* By default use posix locks */
++#include
++#define MLOCK_T pthread_mutex_t
++#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL)
++#define ACQUIRE_LOCK(l) pthread_mutex_lock(l)
++#define RELEASE_LOCK(l) pthread_mutex_unlock(l)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if HAVE_MORECORE
++static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
++#endif /* HAVE_MORECORE */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#elif defined(__OS2__)
++#define MLOCK_T HMTX
++#define INITIAL_LOCK(l) DosCreateMutexSem(0, l, 0, FALSE)
++#define ACQUIRE_LOCK(l) DosRequestMutexSem(*l, SEM_INDEFINITE_WAIT)
++#define RELEASE_LOCK(l) DosReleaseMutexSem(*l)
++#if HAVE_MORECORE
++static MLOCK_T morecore_mutex;
++#endif /* HAVE_MORECORE */
++static MLOCK_T magic_init_mutex;
+
++#else /* WIN32 */
++/*
++ Because lock-protected regions have bounded times, and there
++ are no recursive lock calls, we can use simple spinlocks.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define MLOCK_T long
++static int win32_acquire_lock (MLOCK_T *sl) {
++ for (;;) {
++#ifdef InterlockedCompareExchangePointer
++ if (!InterlockedCompareExchange(sl, 1, 0))
++ return 0;
++#else /* Use older void* version */
++ if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
++ return 0;
++#endif /* InterlockedCompareExchangePointer */
++ Sleep (0);
++ }
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static void win32_release_lock (MLOCK_T *sl) {
++ InterlockedExchange (sl, 0);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define INITIAL_LOCK(l) *(l)=0
++#define ACQUIRE_LOCK(l) win32_acquire_lock(l)
++#define RELEASE_LOCK(l) win32_release_lock(l)
++#if HAVE_MORECORE
++static MLOCK_T morecore_mutex;
++#endif /* HAVE_MORECORE */
++static MLOCK_T magic_init_mutex;
++#endif /* WIN32 */
+
++#define USE_LOCK_BIT (2U)
++#else /* USE_LOCKS */
++#define USE_LOCK_BIT (0U)
++#define INITIAL_LOCK(l)
++#endif /* USE_LOCKS */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if USE_LOCKS && HAVE_MORECORE
++#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex);
++#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex);
++#else /* USE_LOCKS && HAVE_MORECORE */
++#define ACQUIRE_MORECORE_LOCK()
++#define RELEASE_MORECORE_LOCK()
++#endif /* USE_LOCKS && HAVE_MORECORE */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if USE_LOCKS
++#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex);
++#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex);
++#else /* USE_LOCKS */
++#define ACQUIRE_MAGIC_INIT_LOCK()
++#define RELEASE_MAGIC_INIT_LOCK()
++#endif /* USE_LOCKS */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++/* ----------------------- Chunk representations ------------------------ */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ (The following includes lightly edited explanations by Colin Plumb.)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ The malloc_chunk declaration below is misleading (but accurate and
++ necessary). It declares a "view" into memory allowing access to
++ necessary fields at known offsets from a given base.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Chunks of memory are maintained using a `boundary tag' method as
++ originally described by Knuth. (See the paper by Paul Wilson
++ ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
++ techniques.) Sizes of free chunks are stored both in the front of
++ each chunk and at the end. This makes consolidating fragmented
++ chunks into bigger chunks fast. The head fields also hold bits
++ representing whether chunks are free or in use.
+
++ Here are some pictures to make it clearer. They are "exploded" to
++ show that the state of a chunk can be thought of as extending from
++ the high 31 bits of the head field of its header through the
++ prev_foot and PINUSE_BIT bit of the following chunk header.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ A chunk that's in use looks like:
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Size of previous chunk (if P = 1) |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
++ | Size of this chunk 1| +-+
++ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | |
++ +- -+
++ | |
++ +- -+
++ | :
++ +- size - sizeof(size_t) available payload bytes -+
++ : |
++ chunk-> +- -+
++ | |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
++ | Size of next chunk (may or may not be in use) | +-+
++ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ And if it's free, it looks like this:
+
++ chunk-> +- -+
++ | User payload (must be in use, or we would have merged!) |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
++ | Size of this chunk 0| +-+
++ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Next pointer |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Prev pointer |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | :
++ +- size - sizeof(struct chunk) unused bytes -+
++ : |
++ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Size of this chunk |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
++ | Size of next chunk (must be in use, or we would have merged)| +-+
++ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | :
++ +- User payload -+
++ : |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ |0|
++ +-+
++ Note that since we always merge adjacent free chunks, the chunks
++ adjacent to a free chunk must be in use.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Given a pointer to a chunk (which can be derived trivially from the
++ payload pointer) we can, in O(1) time, find out whether the adjacent
++ chunks are free, and if so, unlink them from the lists that they
++ are on and merge them with the current chunk.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Chunks always begin on even word boundaries, so the mem portion
++ (which is returned to the user) is also on an even word boundary, and
++ thus at least double-word aligned.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
++ chunk size (which is always a multiple of two words), is an in-use
++ bit for the *previous* chunk. If that bit is *clear*, then the
++ word before the current chunk size contains the previous chunk
++ size, and can be used to find the front of the previous chunk.
++ The very first chunk allocated always has this bit set, preventing
++ access to non-existent (or non-owned) memory. If pinuse is set for
++ any given chunk, then you CANNOT determine the size of the
++ previous chunk, and might even get a memory addressing fault when
++ trying to do so.
+
++ The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
++ the chunk size redundantly records whether the current chunk is
++ inuse. This redundancy enables usage checks within free and realloc,
++ and reduces indirection when freeing and consolidating chunks.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Each freshly allocated chunk must have both cinuse and pinuse set.
++ That is, each allocated chunk borders either a previously allocated
++ and still in-use chunk, or the base of its memory arena. This is
++ ensured by making all allocations from the the `lowest' part of any
++ found chunk. Further, no free chunk physically borders another one,
++ so each free chunk is known to be preceded and followed by either
++ inuse chunks or the ends of memory.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Note that the `foot' of the current chunk is actually represented
++ as the prev_foot of the NEXT chunk. This makes it easier to
++ deal with alignments etc but can be very confusing when trying
++ to extend or adapt this code.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ The exceptions to all this are
+
++ 1. The special chunk `top' is the top-most available chunk (i.e.,
++ the one bordering the end of available memory). It is treated
++ specially. Top is never included in any bin, is used only if
++ no other chunk is available, and is released back to the
++ system if it is very large (see M_TRIM_THRESHOLD). In effect,
++ the top chunk is treated as larger (and thus less well
++ fitting) than any other available chunk. The top chunk
++ doesn't update its trailing size field since there is no next
++ contiguous chunk that would have to index off it. However,
++ space is still allocated for it (TOP_FOOT_SIZE) to enable
++ separation or merging when space is extended.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ 3. Chunks allocated via mmap, which have the lowest-order bit
++ (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
++ PINUSE_BIT in their head fields. Because they are allocated
++ one-by-one, each must carry its own prev_foot field, which is
++ also used to hold the offset this chunk has within its mmapped
++ region, which is needed to preserve alignment. Each mmapped
++ chunk is trailed by the first two fields of a fake next-chunk
++ for sake of usage checks.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++*/
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++struct malloc_chunk {
++ size_t prev_foot; /* Size of previous chunk (if free). */
++ size_t head; /* Size and inuse bits. */
++ struct malloc_chunk* fd; /* double links -- used only if free. */
++ struct malloc_chunk* bk;
++};
+
++typedef struct malloc_chunk mchunk;
++typedef struct malloc_chunk* mchunkptr;
++typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
++typedef size_t bindex_t; /* Described below */
++typedef unsigned int binmap_t; /* Described below */
++typedef unsigned int flag_t; /* The type of various bit flag sets */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ------------------- Chunks sizes and alignments ----------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define MCHUNK_SIZE (sizeof(mchunk))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if FOOTERS
++#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
++#else /* FOOTERS */
++#define CHUNK_OVERHEAD (SIZE_T_SIZE)
++#endif /* FOOTERS */
+
++/* MMapped chunks need a second word of overhead ... */
++#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
++/* ... and additional padding for fake next-chunk at foot */
++#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* The smallest size we can malloc is an aligned minimal chunk */
++#define MIN_CHUNK_SIZE\
++ ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* conversion from malloc headers to user pointers, and back */
++#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
++#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
++/* chunk associated with aligned address A */
++#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Bounds on request (not chunk) sizes. */
++#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
++#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
+
++/* pad request bytes into a usable size */
++#define pad_request(req) \
++ (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* pad request, checking for minimum (but not maximum) */
++#define request2size(req) \
++ (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* ------------------ Operations on head and foot fields ----------------- */
+
++/*
++ The head field of a chunk is or'ed with PINUSE_BIT when previous
++ adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
++ use. If the chunk was obtained with mmap, the prev_foot field has
++ IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
++ mmapped region to the base of the chunk.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define PINUSE_BIT (SIZE_T_ONE)
++#define CINUSE_BIT (SIZE_T_TWO)
++#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Head value for fenceposts */
++#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* extraction of fields from head words */
++#define cinuse(p) ((p)->head & CINUSE_BIT)
++#define pinuse(p) ((p)->head & PINUSE_BIT)
++#define chunksize(p) ((p)->head & ~(INUSE_BITS))
+
++#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
++#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Treat space at ptr +/- offset as a chunk */
++#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
++#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Ptr to next or previous physical malloc_chunk. */
++#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
++#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* extract next chunk's pinuse bit */
++#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
+
++/* Get/set size at footer */
++#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
++#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Set size, pinuse bit, and foot */
++#define set_size_and_pinuse_of_free_chunk(p, s)\
++ ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Set size, pinuse bit, foot, and clear next pinuse */
++#define set_free_with_pinuse(p, s, n)\
++ (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define is_mmapped(p)\
++ (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
+
++/* Get the internal overhead associated with chunk p */
++#define overhead_for(p)\
++ (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Return true if malloced space is not necessarily cleared */
++#if MMAP_CLEARS
++#define calloc_must_clear(p) (!is_mmapped(p))
++#else /* MMAP_CLEARS */
++#define calloc_must_clear(p) (1)
++#endif /* MMAP_CLEARS */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* ---------------------- Overlaid data structures ----------------------- */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ When chunks are not in use, they are treated as nodes of either
++ lists or trees.
+
++ "Small" chunks are stored in circular doubly-linked lists, and look
++ like this:
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Size of previous chunk |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ `head:' | Size of chunk, in bytes |P|
++ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Forward pointer to next chunk in list |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Back pointer to previous chunk in list |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Unused space (may be 0 bytes long) .
++ . .
++ . |
++nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ `foot:' | Size of chunk, in bytes |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Larger chunks are kept in a form of bitwise digital trees (aka
++ tries) keyed on chunksizes. Because malloc_tree_chunks are only for
++ free chunks greater than 256 bytes, their size doesn't impose any
++ constraints on user chunk sizes. Each node looks like:
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Size of previous chunk |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ `head:' | Size of chunk, in bytes |P|
++ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Forward pointer to next chunk of same size |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Back pointer to previous chunk of same size |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Pointer to left child (child[0]) |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Pointer to right child (child[1]) |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Pointer to parent |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | bin index of this chunk |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ | Unused space .
++ . |
++nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++ `foot:' | Size of chunk, in bytes |
++ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
++ Each tree holding treenodes is a tree of unique chunk sizes. Chunks
++ of the same size are arranged in a circularly-linked list, with only
++ the oldest chunk (the next to be used, in our FIFO ordering)
++ actually in the tree. (Tree members are distinguished by a non-null
++ parent pointer.) If a chunk with the same size an an existing node
++ is inserted, it is linked off the existing node using pointers that
++ work in the same way as fd/bk pointers of small chunks.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Each tree contains a power of 2 sized range of chunk sizes (the
++ smallest is 0x100 <= x < 0x180), which is is divided in half at each
++ tree level, with the chunks in the smaller half of the range (0x100
++ <= x < 0x140 for the top nose) in the left subtree and the larger
++ half (0x140 <= x < 0x180) in the right subtree. This is, of course,
++ done by inspecting individual bits.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Using these rules, each node's left subtree contains all smaller
++ sizes than its right subtree. However, the node at the root of each
++ subtree has no particular ordering relationship to either. (The
++ dividing line between the subtree sizes is based on trie relation.)
++ If we remove the last chunk of a given size from the interior of the
++ tree, we need to replace it with a leaf node. The tree ordering
++ rules permit a node to be replaced by any leaf below it.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ The smallest chunk in a tree (a common operation in a best-fit
++ allocator) can be found by walking a path to the leftmost leaf in
++ the tree. Unlike a usual binary tree, where we follow left child
++ pointers until we reach a null, here we follow the right child
++ pointer any time the left one is null, until we reach a leaf with
++ both child pointers null. The smallest chunk in the tree will be
++ somewhere along that path.
+
++ The worst case number of steps to add, find, or remove a node is
++ bounded by the number of bits differentiating chunks within
++ bins. Under current bin calculations, this ranges from 6 up to 21
++ (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
++ is of course much better.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++struct malloc_tree_chunk {
++ /* The first four fields must be compatible with malloc_chunk */
++ size_t prev_foot;
++ size_t head;
++ struct malloc_tree_chunk* fd;
++ struct malloc_tree_chunk* bk;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ struct malloc_tree_chunk* child[2];
++ struct malloc_tree_chunk* parent;
++ bindex_t index;
++};
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++typedef struct malloc_tree_chunk tchunk;
++typedef struct malloc_tree_chunk* tchunkptr;
++typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
+
++/* A little helper macro for trees */
++#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ----------------------------- Segments -------------------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ Each malloc space may include non-contiguous segments, held in a
++ list headed by an embedded malloc_segment record representing the
++ top-most space. Segments also include flags holding properties of
++ the space. Large chunks that are directly allocated by mmap are not
++ included in this list. They are instead independently created and
++ destroyed without otherwise keeping track of them.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Segment management mainly comes into play for spaces allocated by
++ MMAP. Any call to MMAP might or might not return memory that is
++ adjacent to an existing segment. MORECORE normally contiguously
++ extends the current space, so this space is almost always adjacent,
++ which is simpler and faster to deal with. (This is why MORECORE is
++ used preferentially to MMAP when both are available -- see
++ sys_alloc.) When allocating using MMAP, we don't use any of the
++ hinting mechanisms (inconsistently) supported in various
++ implementations of unix mmap, or distinguish reserving from
++ committing memory. Instead, we just ask for space, and exploit
++ contiguity when we get it. It is probably possible to do
++ better than this on some systems, but no general scheme seems
++ to be significantly better.
+
++ Management entails a simpler variant of the consolidation scheme
++ used for chunks to reduce fragmentation -- new adjacent memory is
++ normally prepended or appended to an existing segment. However,
++ there are limitations compared to chunk consolidation that mostly
++ reflect the fact that segment processing is relatively infrequent
++ (occurring only when getting memory from system) and that we
++ don't expect to have huge numbers of segments:
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ * Segments are not indexed, so traversal requires linear scans. (It
++ would be possible to index these, but is not worth the extra
++ overhead and complexity for most programs on most platforms.)
++ * New segments are only appended to old ones when holding top-most
++ memory; if they cannot be prepended to others, they are held in
++ different segments.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Except for the top-most segment of an mstate, each segment record
++ is kept at the tail of its segment. Segments are added by pushing
++ segment records onto the list headed by &mstate.seg for the
++ containing mstate.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Segment flags control allocation/merge/deallocation policies:
++ * If EXTERN_BIT set, then we did not allocate this segment,
++ and so should not try to deallocate or merge with others.
++ (This currently holds only for the initial segment passed
++ into create_mspace_with_base.)
++ * If IS_MMAPPED_BIT set, the segment may be merged with
++ other surrounding mmapped segments and trimmed/de-allocated
++ using munmap.
++ * If neither bit is set, then the segment was obtained using
++ MORECORE so can be merged with surrounding MORECORE'd segments
++ and deallocated/trimmed using MORECORE with negative arguments.
++*/
+
++struct malloc_segment {
++ char* base; /* base address */
++ size_t size; /* allocated size */
++ struct malloc_segment* next; /* ptr to next segment */
++#if FFI_MMAP_EXEC_WRIT
++ /* The mmap magic is supposed to store the address of the executable
++ segment at the very end of the requested block. */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++# define mmap_exec_offset(b,s) (*(ptrdiff_t*)((b)+(s)-sizeof(ptrdiff_t)))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* We can only merge segments if their corresponding executable
++ segments are at identical offsets. */
++# define check_segment_merge(S,b,s) \
++ (mmap_exec_offset((b),(s)) == (S)->exec_offset)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++# define add_segment_exec_offset(p,S) ((char*)(p) + (S)->exec_offset)
++# define sub_segment_exec_offset(p,S) ((char*)(p) - (S)->exec_offset)
+
++ /* The removal of sflags only works with HAVE_MORECORE == 0. */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++# define get_segment_flags(S) (IS_MMAPPED_BIT)
++# define set_segment_flags(S,v) \
++ (((v) != IS_MMAPPED_BIT) ? (ABORT, (v)) : \
++ (((S)->exec_offset = \
++ mmap_exec_offset((S)->base, (S)->size)), \
++ (mmap_exec_offset((S)->base + (S)->exec_offset, (S)->size) != \
++ (S)->exec_offset) ? (ABORT, (v)) : \
++ (mmap_exec_offset((S)->base, (S)->size) = 0), (v)))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* We use an offset here, instead of a pointer, because then, when
++ base changes, we don't have to modify this. On architectures
++ with segmented addresses, this might not work. */
++ ptrdiff_t exec_offset;
++#else
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++# define get_segment_flags(S) ((S)->sflags)
++# define set_segment_flags(S,v) ((S)->sflags = (v))
++# define check_segment_merge(S,b,s) (1)
+
++ flag_t sflags; /* mmap and extern flag */
++#endif
++};
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define is_mmapped_segment(S) (get_segment_flags(S) & IS_MMAPPED_BIT)
++#define is_extern_segment(S) (get_segment_flags(S) & EXTERN_BIT)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++typedef struct malloc_segment msegment;
++typedef struct malloc_segment* msegmentptr;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* ---------------------------- malloc_state ----------------------------- */
+
++/*
++ A malloc_state holds all of the bookkeeping for a space.
++ The main fields are:
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Top
++ The topmost chunk of the currently active segment. Its size is
++ cached in topsize. The actual size of topmost space is
++ topsize+TOP_FOOT_SIZE, which includes space reserved for adding
++ fenceposts and segment records if necessary when getting more
++ space from the system. The size at which to autotrim top is
++ cached from mparams in trim_check, except that it is disabled if
++ an autotrim fails.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Designated victim (dv)
++ This is the preferred chunk for servicing small requests that
++ don't have exact fits. It is normally the chunk split off most
++ recently to service another small request. Its size is cached in
++ dvsize. The link fields of this chunk are not maintained since it
++ is not kept in a bin.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ SmallBins
++ An array of bin headers for free chunks. These bins hold chunks
++ with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
++ chunks of all the same size, spaced 8 bytes apart. To simplify
++ use in double-linked lists, each bin header acts as a malloc_chunk
++ pointing to the real first node, if it exists (else pointing to
++ itself). This avoids special-casing for headers. But to avoid
++ waste, we allocate only the fd/bk pointers of bins, and then use
++ repositioning tricks to treat these as the fields of a chunk.
+
++ TreeBins
++ Treebins are pointers to the roots of trees holding a range of
++ sizes. There are 2 equally spaced treebins for each power of two
++ from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
++ larger.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Bin maps
++ There is one bit map for small bins ("smallmap") and one for
++ treebins ("treemap). Each bin sets its bit when non-empty, and
++ clears the bit when empty. Bit operations are then used to avoid
++ bin-by-bin searching -- nearly all "search" is done without ever
++ looking at bins that won't be selected. The bit maps
++ conservatively use 32 bits per map word, even if on 64bit system.
++ For a good description of some of the bit-based techniques used
++ here, see Henry S. Warren Jr's book "Hacker's Delight" (and
++ supplement at http://hackersdelight.org/). Many of these are
++ intended to reduce the branchiness of paths through malloc etc, as
++ well as to reduce the number of memory locations read or written.
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Segments
++ A list of segments headed by an embedded malloc_segment record
++ representing the initial space.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Address check support
++ The least_addr field is the least address ever obtained from
++ MORECORE or MMAP. Attempted frees and reallocs of any address less
++ than this are trapped (unless INSECURE is defined).
+
++ Magic tag
++ A cross-check field that should always hold same value as mparams.magic.
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ Flags
++ Bits recording whether to use MMAP, locks, or contiguous MORECORE
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ Statistics
++ Each space keeps track of current and maximum system memory
++ obtained via MORECORE or MMAP.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ Locking
++ If USE_LOCKS is defined, the "mutex" lock is acquired and released
++ around every public call using this mspace.
++*/
+
++/* Bin types, widths and sizes */
++#define NSMALLBINS (32U)
++#define NTREEBINS (32U)
++#define SMALLBIN_SHIFT (3U)
++#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
++#define TREEBIN_SHIFT (8U)
++#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
++#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
++#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++struct malloc_state {
++ binmap_t smallmap;
++ binmap_t treemap;
++ size_t dvsize;
++ size_t topsize;
++ char* least_addr;
++ mchunkptr dv;
++ mchunkptr top;
++ size_t trim_check;
++ size_t magic;
++ mchunkptr smallbins[(NSMALLBINS+1)*2];
++ tbinptr treebins[NTREEBINS];
++ size_t footprint;
++ size_t max_footprint;
++ flag_t mflags;
++#if USE_LOCKS
++ MLOCK_T mutex; /* locate lock among fields that rarely change */
++#endif /* USE_LOCKS */
++ msegment seg;
++};
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++typedef struct malloc_state* mstate;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* ------------- Global malloc_state and malloc_params ------------------- */
+
++/*
++ malloc_params holds global properties, including those that can be
++ dynamically set using mallopt. There is a single instance, mparams,
++ initialized in init_mparams.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++struct malloc_params {
++ size_t magic;
++ size_t page_size;
++ size_t granularity;
++ size_t mmap_threshold;
++ size_t trim_threshold;
++ flag_t default_mflags;
++};
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static struct malloc_params mparams;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* The global malloc_state used for all non-"mspace" calls */
++static struct malloc_state _gm_;
++#define gm (&_gm_)
++#define is_global(M) ((M) == &_gm_)
++#define is_initialized(M) ((M)->top != 0)
+
++/* -------------------------- system alloc setup ------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Operations on mflags */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
++#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
++#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
++#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
++#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
+
++#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
++#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define set_lock(M,L)\
++ ((M)->mflags = (L)?\
++ ((M)->mflags | USE_LOCK_BIT) :\
++ ((M)->mflags & ~USE_LOCK_BIT))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* page-align a size */
++#define page_align(S)\
++ (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* granularity-align a size */
++#define granularity_align(S)\
++ (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
+
++#define is_page_aligned(S)\
++ (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
++#define is_granularity_aligned(S)\
++ (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* True if segment S holds address A */
++#define segment_holds(S, A)\
++ ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Return segment holding given address */
++static msegmentptr segment_holding(mstate m, char* addr) {
++ msegmentptr sp = &m->seg;
++ for (;;) {
++ if (addr >= sp->base && addr < sp->base + sp->size)
++ return sp;
++ if ((sp = sp->next) == 0)
++ return 0;
++ }
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Return true if segment contains a segment link */
++static int has_segment_link(mstate m, msegmentptr ss) {
++ msegmentptr sp = &m->seg;
++ for (;;) {
++ if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
++ return 1;
++ if ((sp = sp->next) == 0)
++ return 0;
++ }
++}
+
++#ifndef MORECORE_CANNOT_TRIM
++#define should_trim(M,s) ((s) > (M)->trim_check)
++#else /* MORECORE_CANNOT_TRIM */
++#define should_trim(M,s) (0)
++#endif /* MORECORE_CANNOT_TRIM */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ TOP_FOOT_SIZE is padding at the end of a segment, including space
++ that may be needed to place segment records and fenceposts when new
++ noncontiguous segments are added.
++*/
++#define TOP_FOOT_SIZE\
++ (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* ------------------------------- Hooks -------------------------------- */
+
++/*
++ PREACTION should be defined to return 0 on success, and nonzero on
++ failure. If you are not using locking, you can redefine these to do
++ anything you like.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if USE_LOCKS
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Ensure locks are initialized */
++#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
++#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
++#else /* USE_LOCKS */
+
++#ifndef PREACTION
++#define PREACTION(M) (0)
++#endif /* PREACTION */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifndef POSTACTION
++#define POSTACTION(M)
++#endif /* POSTACTION */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#endif /* USE_LOCKS */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
++ USAGE_ERROR_ACTION is triggered on detected bad frees and
++ reallocs. The argument p is an address that might have triggered the
++ fault. It is ignored by the two predefined actions, but might be
++ useful in custom actions that try to help diagnose errors.
++*/
+
++#if PROCEED_ON_ERROR
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* A count of the number of corruption errors causing resets */
++int malloc_corruption_error_count;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* default corruption action */
++static void reset_on_error(mstate m);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
++#define USAGE_ERROR_ACTION(m, p)
+
++#else /* PROCEED_ON_ERROR */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#ifndef CORRUPTION_ERROR_ACTION
++#define CORRUPTION_ERROR_ACTION(m) ABORT
++#endif /* CORRUPTION_ERROR_ACTION */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#ifndef USAGE_ERROR_ACTION
++#define USAGE_ERROR_ACTION(m,p) ABORT
++#endif /* USAGE_ERROR_ACTION */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#endif /* PROCEED_ON_ERROR */
+
++/* -------------------------- Debugging setup ---------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if ! DEBUG
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define check_free_chunk(M,P)
++#define check_inuse_chunk(M,P)
++#define check_malloced_chunk(M,P,N)
++#define check_mmapped_chunk(M,P)
++#define check_malloc_state(M)
++#define check_top_chunk(M,P)
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#else /* DEBUG */
++#define check_free_chunk(M,P) do_check_free_chunk(M,P)
++#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
++#define check_top_chunk(M,P) do_check_top_chunk(M,P)
++#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
++#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
++#define check_malloc_state(M) do_check_malloc_state(M)
+
++static void do_check_any_chunk(mstate m, mchunkptr p);
++static void do_check_top_chunk(mstate m, mchunkptr p);
++static void do_check_mmapped_chunk(mstate m, mchunkptr p);
++static void do_check_inuse_chunk(mstate m, mchunkptr p);
++static void do_check_free_chunk(mstate m, mchunkptr p);
++static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
++static void do_check_tree(mstate m, tchunkptr t);
++static void do_check_treebin(mstate m, bindex_t i);
++static void do_check_smallbin(mstate m, bindex_t i);
++static void do_check_malloc_state(mstate m);
++static int bin_find(mstate m, mchunkptr x);
++static size_t traverse_and_check(mstate m);
++#endif /* DEBUG */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ---------------------------- Indexing Bins ---------------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
++#define small_index(s) ((s) >> SMALLBIN_SHIFT)
++#define small_index2size(i) ((i) << SMALLBIN_SHIFT)
++#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* addressing by index. See above about smallbin repositioning */
++#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
++#define treebin_at(M,i) (&((M)->treebins[i]))
+
++/* assign tree index for size S to variable I */
++#if defined(__GNUC__) && defined(__i386__)
++#define compute_tree_index(S, I)\
++{\
++ size_t X = S >> TREEBIN_SHIFT;\
++ if (X == 0)\
++ I = 0;\
++ else if (X > 0xFFFF)\
++ I = NTREEBINS-1;\
++ else {\
++ unsigned int K;\
++ __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\
++ I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
++ }\
++}
++#else /* GNUC */
++#define compute_tree_index(S, I)\
++{\
++ size_t X = S >> TREEBIN_SHIFT;\
++ if (X == 0)\
++ I = 0;\
++ else if (X > 0xFFFF)\
++ I = NTREEBINS-1;\
++ else {\
++ unsigned int Y = (unsigned int)X;\
++ unsigned int N = ((Y - 0x100) >> 16) & 8;\
++ unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
++ N += K;\
++ N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
++ K = 14 - N + ((Y <<= K) >> 15);\
++ I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
++ }\
++}
++#endif /* GNUC */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Bit representing maximum resolved size in a treebin at i */
++#define bit_for_tree_index(i) \
++ (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Shift placing maximum resolved bit in a treebin at i as sign bit */
++#define leftshift_for_tree_index(i) \
++ ((i == NTREEBINS-1)? 0 : \
++ ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* The size of the smallest chunk held in bin with index i */
++#define minsize_for_tree_index(i) \
++ ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
++ (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
+
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ------------------------ Operations on bin maps ----------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* bit corresponding to given index */
++#define idx2bit(i) ((binmap_t)(1) << (i))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Mark/Clear bits with given index */
++#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
++#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
++#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
+
++#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
++#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
++#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* index corresponding to given bit */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if defined(__GNUC__) && defined(__i386__)
++#define compute_bit2idx(X, I)\
++{\
++ unsigned int J;\
++ __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
++ I = (bindex_t)J;\
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#else /* GNUC */
++#if USE_BUILTIN_FFS
++#define compute_bit2idx(X, I) I = ffs(X)-1
+
++#else /* USE_BUILTIN_FFS */
++#define compute_bit2idx(X, I)\
++{\
++ unsigned int Y = X - 1;\
++ unsigned int K = Y >> (16-4) & 16;\
++ unsigned int N = K; Y >>= K;\
++ N += K = Y >> (8-3) & 8; Y >>= K;\
++ N += K = Y >> (4-2) & 4; Y >>= K;\
++ N += K = Y >> (2-1) & 2; Y >>= K;\
++ N += K = Y >> (1-0) & 1; Y >>= K;\
++ I = (bindex_t)(N + Y);\
++}
++#endif /* USE_BUILTIN_FFS */
++#endif /* GNUC */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* isolate the least set bit of a bitmap */
++#define least_bit(x) ((x) & -(x))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* mask with all bits to left of least bit of x on */
++#define left_bits(x) ((x<<1) | -(x<<1))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* mask with all bits to left of or equal to least bit of x on */
++#define same_or_left_bits(x) ((x) | -(x))
+
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ----------------------- Runtime Check Support ------------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ For security, the main invariant is that malloc/free/etc never
++ writes to a static address other than malloc_state, unless static
++ malloc_state itself has been corrupted, which cannot occur via
++ malloc (because of these checks). In essence this means that we
++ believe all pointers, sizes, maps etc held in malloc_state, but
++ check all of those linked or offsetted from other embedded data
++ structures. These checks are interspersed with main code in a way
++ that tends to minimize their run-time cost.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ When FOOTERS is defined, in addition to range checking, we also
++ verify footer fields of inuse chunks, which can be used guarantee
++ that the mstate controlling malloc/free is intact. This is a
++ streamlined version of the approach described by William Robertson
++ et al in "Run-time Detection of Heap-based Overflows" LISA'03
++ http://www.usenix.org/events/lisa03/tech/robertson.html The footer
++ of an inuse chunk holds the xor of its mstate and a random seed,
++ that is checked upon calls to free() and realloc(). This is
++ (probablistically) unguessable from outside the program, but can be
++ computed by any code successfully malloc'ing any chunk, so does not
++ itself provide protection against code that has already broken
++ security through some other means. Unlike Robertson et al, we
++ always dynamically check addresses of all offset chunks (previous,
++ next, etc). This turns out to be cheaper than relying on hashes.
++*/
+
++#if !INSECURE
++/* Check if address a is at least as high as any from MORECORE or MMAP */
++#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
++/* Check if address of next chunk n is higher than base chunk p */
++#define ok_next(p, n) ((char*)(p) < (char*)(n))
++/* Check if p has its cinuse bit on */
++#define ok_cinuse(p) cinuse(p)
++/* Check if p has its pinuse bit on */
++#define ok_pinuse(p) pinuse(p)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#else /* !INSECURE */
++#define ok_address(M, a) (1)
++#define ok_next(b, n) (1)
++#define ok_cinuse(p) (1)
++#define ok_pinuse(p) (1)
++#endif /* !INSECURE */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if (FOOTERS && !INSECURE)
++/* Check if (alleged) mstate m has expected magic field */
++#define ok_magic(M) ((M)->magic == mparams.magic)
++#else /* (FOOTERS && !INSECURE) */
++#define ok_magic(M) (1)
++#endif /* (FOOTERS && !INSECURE) */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++/* In gcc, use __builtin_expect to minimize impact of checks */
++#if !INSECURE
++#if defined(__GNUC__) && __GNUC__ >= 3
++#define RTCHECK(e) __builtin_expect(e, 1)
++#else /* GNUC */
++#define RTCHECK(e) (e)
++#endif /* GNUC */
++#else /* !INSECURE */
++#define RTCHECK(e) (1)
++#endif /* !INSECURE */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* macros to set up inuse chunks with or without footers */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if !FOOTERS
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define mark_inuse_foot(M,p,s)
+
++/* Set cinuse bit and pinuse bit of next chunk */
++#define set_inuse(M,p,s)\
++ ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
++ ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
++#define set_inuse_and_pinuse(M,p,s)\
++ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
++ ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Set size, cinuse and pinuse bit of this chunk */
++#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
++ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#else /* FOOTERS */
+
++/* Set foot of inuse chunk to be xor of mstate and seed */
++#define mark_inuse_foot(M,p,s)\
++ (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#define get_mstate_for(p)\
++ ((mstate)(((mchunkptr)((char*)(p) +\
++ (chunksize(p))))->prev_foot ^ mparams.magic))
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define set_inuse(M,p,s)\
++ ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
++ (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
++ mark_inuse_foot(M,p,s))
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define set_inuse_and_pinuse(M,p,s)\
++ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
++ (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
++ mark_inuse_foot(M,p,s))
+
++#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
++ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
++ mark_inuse_foot(M, p, s))
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#endif /* !FOOTERS */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* ---------------------------- setting mparams -------------------------- */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Initialize mparams */
++static int init_mparams(void) {
++ if (mparams.page_size == 0) {
++ size_t s;
+
++ mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
++ mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
++#if MORECORE_CONTIGUOUS
++ mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
++#else /* MORECORE_CONTIGUOUS */
++ mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
++#endif /* MORECORE_CONTIGUOUS */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if (FOOTERS && !INSECURE)
++ {
++#if USE_DEV_RANDOM
++ int fd;
++ unsigned char buf[sizeof(size_t)];
++ /* Try to use /dev/urandom, else fall back on using time */
++ if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
++ read(fd, buf, sizeof(buf)) == sizeof(buf)) {
++ s = *((size_t *) buf);
++ close(fd);
++ }
++ else
++#endif /* USE_DEV_RANDOM */
++ s = (size_t)(time(0) ^ (size_t)0x55555555U);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ s |= (size_t)8U; /* ensure nonzero */
++ s &= ~(size_t)7U; /* improve chances of fault for bad values */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ }
++#else /* (FOOTERS && !INSECURE) */
++ s = (size_t)0x58585858U;
++#endif /* (FOOTERS && !INSECURE) */
++ ACQUIRE_MAGIC_INIT_LOCK();
++ if (mparams.magic == 0) {
++ mparams.magic = s;
++ /* Set up lock for main malloc area */
++ INITIAL_LOCK(&gm->mutex);
++ gm->mflags = mparams.default_mflags;
++ }
++ RELEASE_MAGIC_INIT_LOCK();
+
++#if !defined(WIN32) && !defined(__OS2__)
++ mparams.page_size = malloc_getpagesize;
++ mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
++ DEFAULT_GRANULARITY : mparams.page_size);
++#elif defined (__OS2__)
++ /* if low-memory is used, os2munmap() would break
++ if it were anything other than 64k */
++ mparams.page_size = 4096u;
++ mparams.granularity = 65536u;
++#else /* WIN32 */
++ {
++ SYSTEM_INFO system_info;
++ GetSystemInfo(&system_info);
++ mparams.page_size = system_info.dwPageSize;
++ mparams.granularity = system_info.dwAllocationGranularity;
++ }
++#endif /* WIN32 */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Sanity-check configuration:
++ size_t must be unsigned and as wide as pointer type.
++ ints must be at least 4 bytes.
++ alignment must be at least 8.
++ Alignment, min chunk size, and page size must all be powers of 2.
++ */
++ if ((sizeof(size_t) != sizeof(char*)) ||
++ (MAX_SIZE_T < MIN_CHUNK_SIZE) ||
++ (sizeof(int) < 4) ||
++ (MALLOC_ALIGNMENT < (size_t)8U) ||
++ ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
++ ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
++ ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
++ ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0))
++ ABORT;
++ }
++ return 0;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* support for mallopt */
++static int change_mparam(int param_number, int value) {
++ size_t val = (size_t)value;
++ init_mparams();
++ switch(param_number) {
++ case M_TRIM_THRESHOLD:
++ mparams.trim_threshold = val;
++ return 1;
++ case M_GRANULARITY:
++ if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
++ mparams.granularity = val;
++ return 1;
++ }
++ else
++ return 0;
++ case M_MMAP_THRESHOLD:
++ mparams.mmap_threshold = val;
++ return 1;
++ default:
++ return 0;
++ }
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if DEBUG
++/* ------------------------- Debugging Support --------------------------- */
+
++/* Check properties of any chunk, whether free, inuse, mmapped etc */
++static void do_check_any_chunk(mstate m, mchunkptr p) {
++ assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
++ assert(ok_address(m, p));
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Check properties of top chunk */
++static void do_check_top_chunk(mstate m, mchunkptr p) {
++ msegmentptr sp = segment_holding(m, (char*)p);
++ size_t sz = chunksize(p);
++ assert(sp != 0);
++ assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
++ assert(ok_address(m, p));
++ assert(sz == m->topsize);
++ assert(sz > 0);
++ assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
++ assert(pinuse(p));
++ assert(!next_pinuse(p));
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Check properties of (inuse) mmapped chunks */
++static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
++ size_t sz = chunksize(p);
++ size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
++ assert(is_mmapped(p));
++ assert(use_mmap(m));
++ assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
++ assert(ok_address(m, p));
++ assert(!is_small(sz));
++ assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
++ assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
++ assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Check properties of inuse chunks */
++static void do_check_inuse_chunk(mstate m, mchunkptr p) {
++ do_check_any_chunk(m, p);
++ assert(cinuse(p));
++ assert(next_pinuse(p));
++ /* If not pinuse and not mmapped, previous chunk has OK offset */
++ assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
++ if (is_mmapped(p))
++ do_check_mmapped_chunk(m, p);
++}
+
++/* Check properties of free chunks */
++static void do_check_free_chunk(mstate m, mchunkptr p) {
++ size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
++ mchunkptr next = chunk_plus_offset(p, sz);
++ do_check_any_chunk(m, p);
++ assert(!cinuse(p));
++ assert(!next_pinuse(p));
++ assert (!is_mmapped(p));
++ if (p != m->dv && p != m->top) {
++ if (sz >= MIN_CHUNK_SIZE) {
++ assert((sz & CHUNK_ALIGN_MASK) == 0);
++ assert(is_aligned(chunk2mem(p)));
++ assert(next->prev_foot == sz);
++ assert(pinuse(p));
++ assert (next == m->top || cinuse(next));
++ assert(p->fd->bk == p);
++ assert(p->bk->fd == p);
++ }
++ else /* markers are always of size SIZE_T_SIZE */
++ assert(sz == SIZE_T_SIZE);
++ }
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Check properties of malloced chunks at the point they are malloced */
++static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
++ if (mem != 0) {
++ mchunkptr p = mem2chunk(mem);
++ size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
++ do_check_inuse_chunk(m, p);
++ assert((sz & CHUNK_ALIGN_MASK) == 0);
++ assert(sz >= MIN_CHUNK_SIZE);
++ assert(sz >= s);
++ /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
++ assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
++ }
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Check a tree and its subtrees. */
++static void do_check_tree(mstate m, tchunkptr t) {
++ tchunkptr head = 0;
++ tchunkptr u = t;
++ bindex_t tindex = t->index;
++ size_t tsize = chunksize(t);
++ bindex_t idx;
++ compute_tree_index(tsize, idx);
++ assert(tindex == idx);
++ assert(tsize >= MIN_LARGE_SIZE);
++ assert(tsize >= minsize_for_tree_index(idx));
++ assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ do { /* traverse through chain of same-sized nodes */
++ do_check_any_chunk(m, ((mchunkptr)u));
++ assert(u->index == tindex);
++ assert(chunksize(u) == tsize);
++ assert(!cinuse(u));
++ assert(!next_pinuse(u));
++ assert(u->fd->bk == u);
++ assert(u->bk->fd == u);
++ if (u->parent == 0) {
++ assert(u->child[0] == 0);
++ assert(u->child[1] == 0);
++ }
++ else {
++ assert(head == 0); /* only one node on chain has parent */
++ head = u;
++ assert(u->parent != u);
++ assert (u->parent->child[0] == u ||
++ u->parent->child[1] == u ||
++ *((tbinptr*)(u->parent)) == u);
++ if (u->child[0] != 0) {
++ assert(u->child[0]->parent == u);
++ assert(u->child[0] != u);
++ do_check_tree(m, u->child[0]);
++ }
++ if (u->child[1] != 0) {
++ assert(u->child[1]->parent == u);
++ assert(u->child[1] != u);
++ do_check_tree(m, u->child[1]);
++ }
++ if (u->child[0] != 0 && u->child[1] != 0) {
++ assert(chunksize(u->child[0]) < chunksize(u->child[1]));
++ }
++ }
++ u = u->fd;
++ } while (u != t);
++ assert(head != 0);
++}
+
++/* Check all the chunks in a treebin. */
++static void do_check_treebin(mstate m, bindex_t i) {
++ tbinptr* tb = treebin_at(m, i);
++ tchunkptr t = *tb;
++ int empty = (m->treemap & (1U << i)) == 0;
++ if (t == 0)
++ assert(empty);
++ if (!empty)
++ do_check_tree(m, t);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Check all the chunks in a smallbin. */
++static void do_check_smallbin(mstate m, bindex_t i) {
++ sbinptr b = smallbin_at(m, i);
++ mchunkptr p = b->bk;
++ unsigned int empty = (m->smallmap & (1U << i)) == 0;
++ if (p == b)
++ assert(empty);
++ if (!empty) {
++ for (; p != b; p = p->bk) {
++ size_t size = chunksize(p);
++ mchunkptr q;
++ /* each chunk claims to be free */
++ do_check_free_chunk(m, p);
++ /* chunk belongs in bin */
++ assert(small_index(size) == i);
++ assert(p->bk == b || chunksize(p->bk) == chunksize(p));
++ /* chunk is followed by an inuse chunk */
++ q = next_chunk(p);
++ if (q->head != FENCEPOST_HEAD)
++ do_check_inuse_chunk(m, q);
++ }
++ }
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Find x in a bin. Used in other check functions. */
++static int bin_find(mstate m, mchunkptr x) {
++ size_t size = chunksize(x);
++ if (is_small(size)) {
++ bindex_t sidx = small_index(size);
++ sbinptr b = smallbin_at(m, sidx);
++ if (smallmap_is_marked(m, sidx)) {
++ mchunkptr p = b;
++ do {
++ if (p == x)
++ return 1;
++ } while ((p = p->fd) != b);
++ }
++ }
++ else {
++ bindex_t tidx;
++ compute_tree_index(size, tidx);
++ if (treemap_is_marked(m, tidx)) {
++ tchunkptr t = *treebin_at(m, tidx);
++ size_t sizebits = size << leftshift_for_tree_index(tidx);
++ while (t != 0 && chunksize(t) != size) {
++ t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
++ sizebits <<= 1;
++ }
++ if (t != 0) {
++ tchunkptr u = t;
++ do {
++ if (u == (tchunkptr)x)
++ return 1;
++ } while ((u = u->fd) != t);
++ }
++ }
++ }
++ return 0;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Traverse each chunk and check it; return total */
++static size_t traverse_and_check(mstate m) {
++ size_t sum = 0;
++ if (is_initialized(m)) {
++ msegmentptr s = &m->seg;
++ sum += m->topsize + TOP_FOOT_SIZE;
++ while (s != 0) {
++ mchunkptr q = align_as_chunk(s->base);
++ mchunkptr lastq = 0;
++ assert(pinuse(q));
++ while (segment_holds(s, q) &&
++ q != m->top && q->head != FENCEPOST_HEAD) {
++ sum += chunksize(q);
++ if (cinuse(q)) {
++ assert(!bin_find(m, q));
++ do_check_inuse_chunk(m, q);
++ }
++ else {
++ assert(q == m->dv || bin_find(m, q));
++ assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
++ do_check_free_chunk(m, q);
++ }
++ lastq = q;
++ q = next_chunk(q);
++ }
++ s = s->next;
++ }
++ }
++ return sum;
++}
+
++/* Check all properties of malloc_state. */
++static void do_check_malloc_state(mstate m) {
++ bindex_t i;
++ size_t total;
++ /* check bins */
++ for (i = 0; i < NSMALLBINS; ++i)
++ do_check_smallbin(m, i);
++ for (i = 0; i < NTREEBINS; ++i)
++ do_check_treebin(m, i);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (m->dvsize != 0) { /* check dv chunk */
++ do_check_any_chunk(m, m->dv);
++ assert(m->dvsize == chunksize(m->dv));
++ assert(m->dvsize >= MIN_CHUNK_SIZE);
++ assert(bin_find(m, m->dv) == 0);
++ }
+
++ if (m->top != 0) { /* check top chunk */
++ do_check_top_chunk(m, m->top);
++ assert(m->topsize == chunksize(m->top));
++ assert(m->topsize > 0);
++ assert(bin_find(m, m->top) == 0);
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ total = traverse_and_check(m);
++ assert(total <= m->footprint);
++ assert(m->footprint <= m->max_footprint);
++}
++#endif /* DEBUG */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* ----------------------------- statistics ------------------------------ */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if !NO_MALLINFO
++static struct mallinfo internal_mallinfo(mstate m) {
++ struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
++ if (!PREACTION(m)) {
++ check_malloc_state(m);
++ if (is_initialized(m)) {
++ size_t nfree = SIZE_T_ONE; /* top always free */
++ size_t mfree = m->topsize + TOP_FOOT_SIZE;
++ size_t sum = mfree;
++ msegmentptr s = &m->seg;
++ while (s != 0) {
++ mchunkptr q = align_as_chunk(s->base);
++ while (segment_holds(s, q) &&
++ q != m->top && q->head != FENCEPOST_HEAD) {
++ size_t sz = chunksize(q);
++ sum += sz;
++ if (!cinuse(q)) {
++ mfree += sz;
++ ++nfree;
++ }
++ q = next_chunk(q);
++ }
++ s = s->next;
++ }
+
++ nm.arena = sum;
++ nm.ordblks = nfree;
++ nm.hblkhd = m->footprint - sum;
++ nm.usmblks = m->max_footprint;
++ nm.uordblks = m->footprint - mfree;
++ nm.fordblks = mfree;
++ nm.keepcost = m->topsize;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ POSTACTION(m);
++ }
++ return nm;
++}
++#endif /* !NO_MALLINFO */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static void internal_malloc_stats(mstate m) {
++ if (!PREACTION(m)) {
++ size_t maxfp = 0;
++ size_t fp = 0;
++ size_t used = 0;
++ check_malloc_state(m);
++ if (is_initialized(m)) {
++ msegmentptr s = &m->seg;
++ maxfp = m->max_footprint;
++ fp = m->footprint;
++ used = fp - (m->topsize + TOP_FOOT_SIZE);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ while (s != 0) {
++ mchunkptr q = align_as_chunk(s->base);
++ while (segment_holds(s, q) &&
++ q != m->top && q->head != FENCEPOST_HEAD) {
++ if (!cinuse(q))
++ used -= chunksize(q);
++ q = next_chunk(q);
++ }
++ s = s->next;
++ }
++ }
+
++ fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
++ fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
++ fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ POSTACTION(m);
++ }
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* ----------------------- Operations on smallbins ----------------------- */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/*
++ Various forms of linking and unlinking are defined as macros. Even
++ the ones for trees, which are very long but have very short typical
++ paths. This is ugly but reduces reliance on inlining support of
++ compilers.
++*/
+
++/* Link a free chunk into a smallbin */
++#define insert_small_chunk(M, P, S) {\
++ bindex_t I = small_index(S);\
++ mchunkptr B = smallbin_at(M, I);\
++ mchunkptr F = B;\
++ assert(S >= MIN_CHUNK_SIZE);\
++ if (!smallmap_is_marked(M, I))\
++ mark_smallmap(M, I);\
++ else if (RTCHECK(ok_address(M, B->fd)))\
++ F = B->fd;\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++ B->fd = P;\
++ F->bk = P;\
++ P->fd = F;\
++ P->bk = B;\
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Unlink a chunk from a smallbin */
++#define unlink_small_chunk(M, P, S) {\
++ mchunkptr F = P->fd;\
++ mchunkptr B = P->bk;\
++ bindex_t I = small_index(S);\
++ assert(P != B);\
++ assert(P != F);\
++ assert(chunksize(P) == small_index2size(I));\
++ if (F == B)\
++ clear_smallmap(M, I);\
++ else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
++ (B == smallbin_at(M,I) || ok_address(M, B)))) {\
++ F->bk = B;\
++ B->fd = F;\
++ }\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Unlink the first chunk from a smallbin */
++#define unlink_first_small_chunk(M, B, P, I) {\
++ mchunkptr F = P->fd;\
++ assert(P != B);\
++ assert(P != F);\
++ assert(chunksize(P) == small_index2size(I));\
++ if (B == F)\
++ clear_smallmap(M, I);\
++ else if (RTCHECK(ok_address(M, F))) {\
++ B->fd = F;\
++ F->bk = B;\
++ }\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Replace dv node, binning the old one */
++/* Used only when dvsize known to be small */
++#define replace_dv(M, P, S) {\
++ size_t DVS = M->dvsize;\
++ if (DVS != 0) {\
++ mchunkptr DV = M->dv;\
++ assert(is_small(DVS));\
++ insert_small_chunk(M, DV, DVS);\
++ }\
++ M->dvsize = S;\
++ M->dv = P;\
++}
+
++/* ------------------------- Operations on trees ------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Insert chunk into tree */
++#define insert_large_chunk(M, X, S) {\
++ tbinptr* H;\
++ bindex_t I;\
++ compute_tree_index(S, I);\
++ H = treebin_at(M, I);\
++ X->index = I;\
++ X->child[0] = X->child[1] = 0;\
++ if (!treemap_is_marked(M, I)) {\
++ mark_treemap(M, I);\
++ *H = X;\
++ X->parent = (tchunkptr)H;\
++ X->fd = X->bk = X;\
++ }\
++ else {\
++ tchunkptr T = *H;\
++ size_t K = S << leftshift_for_tree_index(I);\
++ for (;;) {\
++ if (chunksize(T) != S) {\
++ tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
++ K <<= 1;\
++ if (*C != 0)\
++ T = *C;\
++ else if (RTCHECK(ok_address(M, C))) {\
++ *C = X;\
++ X->parent = T;\
++ X->fd = X->bk = X;\
++ break;\
++ }\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ break;\
++ }\
++ }\
++ else {\
++ tchunkptr F = T->fd;\
++ if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
++ T->fd = F->bk = X;\
++ X->fd = F;\
++ X->bk = T;\
++ X->parent = 0;\
++ break;\
++ }\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ break;\
++ }\
++ }\
++ }\
++ }\
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/*
++ Unlink steps:
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ 1. If x is a chained node, unlink it from its same-sized fd/bk links
++ and choose its bk node as its replacement.
++ 2. If x was the last node of its size, but not a leaf node, it must
++ be replaced with a leaf node (not merely one with an open left or
++ right), to make sure that lefts and rights of descendants
++ correspond properly to bit masks. We use the rightmost descendant
++ of x. We could use any other leaf, but this is easy to locate and
++ tends to counteract removal of leftmosts elsewhere, and so keeps
++ paths shorter than minimally guaranteed. This doesn't loop much
++ because on average a node in a tree is near the bottom.
++ 3. If x is the base of a chain (i.e., has parent links) relink
++ x's parent and children to x's replacement (or null if none).
++*/
+
++#define unlink_large_chunk(M, X) {\
++ tchunkptr XP = X->parent;\
++ tchunkptr R;\
++ if (X->bk != X) {\
++ tchunkptr F = X->fd;\
++ R = X->bk;\
++ if (RTCHECK(ok_address(M, F))) {\
++ F->bk = R;\
++ R->fd = F;\
++ }\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++ }\
++ else {\
++ tchunkptr* RP;\
++ if (((R = *(RP = &(X->child[1]))) != 0) ||\
++ ((R = *(RP = &(X->child[0]))) != 0)) {\
++ tchunkptr* CP;\
++ while ((*(CP = &(R->child[1])) != 0) ||\
++ (*(CP = &(R->child[0])) != 0)) {\
++ R = *(RP = CP);\
++ }\
++ if (RTCHECK(ok_address(M, RP)))\
++ *RP = 0;\
++ else {\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++ }\
++ }\
++ if (XP != 0) {\
++ tbinptr* H = treebin_at(M, X->index);\
++ if (X == *H) {\
++ if ((*H = R) == 0) \
++ clear_treemap(M, X->index);\
++ }\
++ else if (RTCHECK(ok_address(M, XP))) {\
++ if (XP->child[0] == X) \
++ XP->child[0] = R;\
++ else \
++ XP->child[1] = R;\
++ }\
++ else\
++ CORRUPTION_ERROR_ACTION(M);\
++ if (R != 0) {\
++ if (RTCHECK(ok_address(M, R))) {\
++ tchunkptr C0, C1;\
++ R->parent = XP;\
++ if ((C0 = X->child[0]) != 0) {\
++ if (RTCHECK(ok_address(M, C0))) {\
++ R->child[0] = C0;\
++ C0->parent = R;\
++ }\
++ else\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++ if ((C1 = X->child[1]) != 0) {\
++ if (RTCHECK(ok_address(M, C1))) {\
++ R->child[1] = C1;\
++ C1->parent = R;\
++ }\
++ else\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++ }\
++ else\
++ CORRUPTION_ERROR_ACTION(M);\
++ }\
++ }\
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Relays to large vs small bin operations */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#define insert_chunk(M, P, S)\
++ if (is_small(S)) insert_small_chunk(M, P, S)\
++ else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#define unlink_chunk(M, P, S)\
++ if (is_small(S)) unlink_small_chunk(M, P, S)\
++ else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
+
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Relays to internal calls to malloc/free from realloc, memalign etc */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if ONLY_MSPACES
++#define internal_malloc(m, b) mspace_malloc(m, b)
++#define internal_free(m, mem) mspace_free(m,mem);
++#else /* ONLY_MSPACES */
++#if MSPACES
++#define internal_malloc(m, b)\
++ (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
++#define internal_free(m, mem)\
++ if (m == gm) dlfree(mem); else mspace_free(m,mem);
++#else /* MSPACES */
++#define internal_malloc(m, b) dlmalloc(b)
++#define internal_free(m, mem) dlfree(mem)
++#endif /* MSPACES */
++#endif /* ONLY_MSPACES */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* ----------------------- Direct-mmapping chunks ----------------------- */
+
++/*
++ Directly mmapped chunks are set up with an offset to the start of
++ the mmapped region stored in the prev_foot field of the chunk. This
++ allows reconstruction of the required argument to MUNMAP when freed,
++ and also allows adjustment of the returned chunk to meet alignment
++ requirements (especially in memalign). There is also enough space
++ allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
++ the PINUSE bit so frees can be checked.
++*/
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Malloc using mmap */
++static void* mmap_alloc(mstate m, size_t nb) {
++ size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
++ if (mmsize > nb) { /* Check for wrap around 0 */
++ char* mm = (char*)(DIRECT_MMAP(mmsize));
++ if (mm != CMFAIL) {
++ size_t offset = align_offset(chunk2mem(mm));
++ size_t psize = mmsize - offset - MMAP_FOOT_PAD;
++ mchunkptr p = (mchunkptr)(mm + offset);
++ p->prev_foot = offset | IS_MMAPPED_BIT;
++ (p)->head = (psize|CINUSE_BIT);
++ mark_inuse_foot(m, p, psize);
++ chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
++ chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (mm < m->least_addr)
++ m->least_addr = mm;
++ if ((m->footprint += mmsize) > m->max_footprint)
++ m->max_footprint = m->footprint;
++ assert(is_aligned(chunk2mem(p)));
++ check_mmapped_chunk(m, p);
++ return chunk2mem(p);
++ }
++ }
++ return 0;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Realloc using mmap */
++static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
++ size_t oldsize = chunksize(oldp);
++ if (is_small(nb)) /* Can't shrink mmap regions below small size */
++ return 0;
++ /* Keep old chunk if big enough but not too big */
++ if (oldsize >= nb + SIZE_T_SIZE &&
++ (oldsize - nb) <= (mparams.granularity << 1))
++ return oldp;
++ else {
++ size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
++ size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
++ size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
++ CHUNK_ALIGN_MASK);
++ char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
++ oldmmsize, newmmsize, 1);
++ if (cp != CMFAIL) {
++ mchunkptr newp = (mchunkptr)(cp + offset);
++ size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
++ newp->head = (psize|CINUSE_BIT);
++ mark_inuse_foot(m, newp, psize);
++ chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
++ chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
+
++ if (cp < m->least_addr)
++ m->least_addr = cp;
++ if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
++ m->max_footprint = m->footprint;
++ check_mmapped_chunk(m, newp);
++ return newp;
++ }
++ }
++ return 0;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* -------------------------- mspace management -------------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* Initialize top chunk and its size */
++static void init_top(mstate m, mchunkptr p, size_t psize) {
++ /* Ensure alignment */
++ size_t offset = align_offset(chunk2mem(p));
++ p = (mchunkptr)((char*)p + offset);
++ psize -= offset;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ m->top = p;
++ m->topsize = psize;
++ p->head = psize | PINUSE_BIT;
++ /* set size of fake trailing chunk holding overhead space only once */
++ chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
++ m->trim_check = mparams.trim_threshold; /* reset on each update */
++}
+
++/* Initialize bins for a new mstate that is otherwise zeroed out */
++static void init_bins(mstate m) {
++ /* Establish circular links for smallbins */
++ bindex_t i;
++ for (i = 0; i < NSMALLBINS; ++i) {
++ sbinptr bin = smallbin_at(m,i);
++ bin->fd = bin->bk = bin;
++ }
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if PROCEED_ON_ERROR
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* default corruption action */
++static void reset_on_error(mstate m) {
++ int i;
++ ++malloc_corruption_error_count;
++ /* Reinitialize fields to forget about all memory */
++ m->smallbins = m->treebins = 0;
++ m->dvsize = m->topsize = 0;
++ m->seg.base = 0;
++ m->seg.size = 0;
++ m->seg.next = 0;
++ m->top = m->dv = 0;
++ for (i = 0; i < NTREEBINS; ++i)
++ *treebin_at(m, i) = 0;
++ init_bins(m);
++}
++#endif /* PROCEED_ON_ERROR */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* Allocate chunk and prepend remainder with chunk in successor base. */
++static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
++ size_t nb) {
++ mchunkptr p = align_as_chunk(newbase);
++ mchunkptr oldfirst = align_as_chunk(oldbase);
++ size_t psize = (char*)oldfirst - (char*)p;
++ mchunkptr q = chunk_plus_offset(p, nb);
++ size_t qsize = psize - nb;
++ set_size_and_pinuse_of_inuse_chunk(m, p, nb);
+
++ assert((char*)oldfirst > (char*)q);
++ assert(pinuse(oldfirst));
++ assert(qsize >= MIN_CHUNK_SIZE);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* consolidate remainder with first chunk of old base */
++ if (oldfirst == m->top) {
++ size_t tsize = m->topsize += qsize;
++ m->top = q;
++ q->head = tsize | PINUSE_BIT;
++ check_top_chunk(m, q);
++ }
++ else if (oldfirst == m->dv) {
++ size_t dsize = m->dvsize += qsize;
++ m->dv = q;
++ set_size_and_pinuse_of_free_chunk(q, dsize);
++ }
++ else {
++ if (!cinuse(oldfirst)) {
++ size_t nsize = chunksize(oldfirst);
++ unlink_chunk(m, oldfirst, nsize);
++ oldfirst = chunk_plus_offset(oldfirst, nsize);
++ qsize += nsize;
++ }
++ set_free_with_pinuse(q, qsize, oldfirst);
++ insert_chunk(m, q, qsize);
++ check_free_chunk(m, q);
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ check_malloced_chunk(m, chunk2mem(p), nb);
++ return chunk2mem(p);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
+
++/* Add a segment to hold a new noncontiguous region */
++static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
++ /* Determine locations and sizes of segment, fenceposts, old top */
++ char* old_top = (char*)m->top;
++ msegmentptr oldsp = segment_holding(m, old_top);
++ char* old_end = oldsp->base + oldsp->size;
++ size_t ssize = pad_request(sizeof(struct malloc_segment));
++ char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
++ size_t offset = align_offset(chunk2mem(rawsp));
++ char* asp = rawsp + offset;
++ char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
++ mchunkptr sp = (mchunkptr)csp;
++ msegmentptr ss = (msegmentptr)(chunk2mem(sp));
++ mchunkptr tnext = chunk_plus_offset(sp, ssize);
++ mchunkptr p = tnext;
++ int nfences = 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* reset top to new space */
++ init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Set up segment record */
++ assert(is_aligned(ss));
++ set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
++ *ss = m->seg; /* Push current record */
++ m->seg.base = tbase;
++ m->seg.size = tsize;
++ (void)set_segment_flags(&m->seg, mmapped);
++ m->seg.next = ss;
+
++ /* Insert trailing fenceposts */
++ for (;;) {
++ mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
++ p->head = FENCEPOST_HEAD;
++ ++nfences;
++ if ((char*)(&(nextp->head)) < old_end)
++ p = nextp;
++ else
++ break;
++ }
++ assert(nfences >= 2);
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Insert the rest of old top into a bin as an ordinary free chunk */
++ if (csp != old_top) {
++ mchunkptr q = (mchunkptr)old_top;
++ size_t psize = csp - old_top;
++ mchunkptr tn = chunk_plus_offset(q, psize);
++ set_free_with_pinuse(q, psize, tn);
++ insert_chunk(m, q, psize);
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ check_top_chunk(m, m->top);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* -------------------------- System allocation -------------------------- */
+
++/* Get memory from system using MORECORE or MMAP */
++static void* sys_alloc(mstate m, size_t nb) {
++ char* tbase = CMFAIL;
++ size_t tsize = 0;
++ flag_t mmap_flag = 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ init_mparams();
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* Directly map large chunks */
++ if (use_mmap(m) && nb >= mparams.mmap_threshold) {
++ void* mem = mmap_alloc(m, nb);
++ if (mem != 0)
++ return mem;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /*
++ Try getting memory in any of three ways (in most-preferred to
++ least-preferred order):
++ 1. A call to MORECORE that can normally contiguously extend memory.
++ (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
++ or main space is mmapped or a previous contiguous call failed)
++ 2. A call to MMAP new space (disabled if not HAVE_MMAP).
++ Note that under the default settings, if MORECORE is unable to
++ fulfill a request, and HAVE_MMAP is true, then mmap is
++ used as a noncontiguous system allocator. This is a useful backup
++ strategy for systems with holes in address spaces -- in this case
++ sbrk cannot contiguously expand the heap, but mmap may be able to
++ find space.
++ 3. A call to MORECORE that cannot usually contiguously extend memory.
++ (disabled if not HAVE_MORECORE)
++ */
+
++ if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
++ char* br = CMFAIL;
++ msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
++ size_t asize = 0;
++ ACQUIRE_MORECORE_LOCK();
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (ss == 0) { /* First time through or recovery */
++ char* base = (char*)CALL_MORECORE(0);
++ if (base != CMFAIL) {
++ asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
++ /* Adjust to end on a page boundary */
++ if (!is_page_aligned(base))
++ asize += (page_align((size_t)base) - (size_t)base);
++ /* Can't call MORECORE if size is negative when treated as signed */
++ if (asize < HALF_MAX_SIZE_T &&
++ (br = (char*)(CALL_MORECORE(asize))) == base) {
++ tbase = base;
++ tsize = asize;
++ }
++ }
++ }
++ else {
++ /* Subtract out existing available top space from MORECORE request. */
++ asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
++ /* Use mem here only if it did continuously extend old space */
++ if (asize < HALF_MAX_SIZE_T &&
++ (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
++ tbase = br;
++ tsize = asize;
++ }
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (tbase == CMFAIL) { /* Cope with partial failure */
++ if (br != CMFAIL) { /* Try to use/extend the space we did get */
++ if (asize < HALF_MAX_SIZE_T &&
++ asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
++ size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
++ if (esize < HALF_MAX_SIZE_T) {
++ char* end = (char*)CALL_MORECORE(esize);
++ if (end != CMFAIL)
++ asize += esize;
++ else { /* Can't use; try to release */
++ (void)CALL_MORECORE(-asize);
++ br = CMFAIL;
++ }
++ }
++ }
++ }
++ if (br != CMFAIL) { /* Use the space we did get */
++ tbase = br;
++ tsize = asize;
++ }
++ else
++ disable_contiguous(m); /* Don't try contiguous path in the future */
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ RELEASE_MORECORE_LOCK();
++ }
+
++ if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */
++ size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
++ size_t rsize = granularity_align(req);
++ if (rsize > nb) { /* Fail if wraps around zero */
++ char* mp = (char*)(CALL_MMAP(rsize));
++ if (mp != CMFAIL) {
++ tbase = mp;
++ tsize = rsize;
++ mmap_flag = IS_MMAPPED_BIT;
++ }
++ }
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
++ size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
++ if (asize < HALF_MAX_SIZE_T) {
++ char* br = CMFAIL;
++ char* end = CMFAIL;
++ ACQUIRE_MORECORE_LOCK();
++ br = (char*)(CALL_MORECORE(asize));
++ end = (char*)(CALL_MORECORE(0));
++ RELEASE_MORECORE_LOCK();
++ if (br != CMFAIL && end != CMFAIL && br < end) {
++ size_t ssize = end - br;
++ if (ssize > nb + TOP_FOOT_SIZE) {
++ tbase = br;
++ tsize = ssize;
++ }
++ }
++ }
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (tbase != CMFAIL) {
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if ((m->footprint += tsize) > m->max_footprint)
++ m->max_footprint = m->footprint;
+
++ if (!is_initialized(m)) { /* first-time initialization */
++ m->seg.base = m->least_addr = tbase;
++ m->seg.size = tsize;
++ (void)set_segment_flags(&m->seg, mmap_flag);
++ m->magic = mparams.magic;
++ init_bins(m);
++ if (is_global(m))
++ init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
++ else {
++ /* Offset top by embedded malloc_state */
++ mchunkptr mn = next_chunk(mem2chunk(m));
++ init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
++ }
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ else {
++ /* Try to merge with an existing segment */
++ msegmentptr sp = &m->seg;
++ while (sp != 0 && tbase != sp->base + sp->size)
++ sp = sp->next;
++ if (sp != 0 &&
++ !is_extern_segment(sp) &&
++ check_segment_merge(sp, tbase, tsize) &&
++ (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag &&
++ segment_holds(sp, m->top)) { /* append */
++ sp->size += tsize;
++ init_top(m, m->top, m->topsize + tsize);
++ }
++ else {
++ if (tbase < m->least_addr)
++ m->least_addr = tbase;
++ sp = &m->seg;
++ while (sp != 0 && sp->base != tbase + tsize)
++ sp = sp->next;
++ if (sp != 0 &&
++ !is_extern_segment(sp) &&
++ check_segment_merge(sp, tbase, tsize) &&
++ (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag) {
++ char* oldbase = sp->base;
++ sp->base = tbase;
++ sp->size += tsize;
++ return prepend_alloc(m, tbase, oldbase, nb);
++ }
++ else
++ add_segment(m, tbase, tsize, mmap_flag);
++ }
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (nb < m->topsize) { /* Allocate from new or extended top space */
++ size_t rsize = m->topsize -= nb;
++ mchunkptr p = m->top;
++ mchunkptr r = m->top = chunk_plus_offset(p, nb);
++ r->head = rsize | PINUSE_BIT;
++ set_size_and_pinuse_of_inuse_chunk(m, p, nb);
++ check_top_chunk(m, m->top);
++ check_malloced_chunk(m, chunk2mem(p), nb);
++ return chunk2mem(p);
++ }
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ MALLOC_FAILURE_ACTION;
++ return 0;
++}
+
++/* ----------------------- system deallocation -------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* Unmap and unlink any mmapped segments that don't contain used chunks */
++static size_t release_unused_segments(mstate m) {
++ size_t released = 0;
++ msegmentptr pred = &m->seg;
++ msegmentptr sp = pred->next;
++ while (sp != 0) {
++ char* base = sp->base;
++ size_t size = sp->size;
++ msegmentptr next = sp->next;
++ if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
++ mchunkptr p = align_as_chunk(base);
++ size_t psize = chunksize(p);
++ /* Can unmap if first chunk holds entire segment and not pinned */
++ if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
++ tchunkptr tp = (tchunkptr)p;
++ assert(segment_holds(sp, (char*)sp));
++ if (p == m->dv) {
++ m->dv = 0;
++ m->dvsize = 0;
++ }
++ else {
++ unlink_large_chunk(m, tp);
++ }
++ if (CALL_MUNMAP(base, size) == 0) {
++ released += size;
++ m->footprint -= size;
++ /* unlink obsoleted record */
++ sp = pred;
++ sp->next = next;
++ }
++ else { /* back out if cannot unmap */
++ insert_large_chunk(m, tp, psize);
++ }
++ }
++ }
++ pred = sp;
++ sp = next;
++ }
++ return released;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static int sys_trim(mstate m, size_t pad) {
++ size_t released = 0;
++ if (pad < MAX_REQUEST && is_initialized(m)) {
++ pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (m->topsize > pad) {
++ /* Shrink top space in granularity-size units, keeping at least one */
++ size_t unit = mparams.granularity;
++ size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
++ SIZE_T_ONE) * unit;
++ msegmentptr sp = segment_holding(m, (char*)m->top);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (!is_extern_segment(sp)) {
++ if (is_mmapped_segment(sp)) {
++ if (HAVE_MMAP &&
++ sp->size >= extra &&
++ !has_segment_link(m, sp)) { /* can't shrink if pinned */
++ size_t newsize = sp->size - extra;
++ /* Prefer mremap, fall back to munmap */
++ if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
++ (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
++ released = extra;
++ }
++ }
++ }
++ else if (HAVE_MORECORE) {
++ if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
++ extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
++ ACQUIRE_MORECORE_LOCK();
++ {
++ /* Make sure end of memory is where we last set it. */
++ char* old_br = (char*)(CALL_MORECORE(0));
++ if (old_br == sp->base + sp->size) {
++ char* rel_br = (char*)(CALL_MORECORE(-extra));
++ char* new_br = (char*)(CALL_MORECORE(0));
++ if (rel_br != CMFAIL && new_br < old_br)
++ released = old_br - new_br;
++ }
++ }
++ RELEASE_MORECORE_LOCK();
++ }
++ }
+
++ if (released != 0) {
++ sp->size -= released;
++ m->footprint -= released;
++ init_top(m, m->top, m->topsize - released);
++ check_top_chunk(m, m->top);
++ }
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Unmap any unused mmapped segments */
++ if (HAVE_MMAP)
++ released += release_unused_segments(m);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* On failure, disable autotrim to avoid repeated failed future calls */
++ if (released == 0)
++ m->trim_check = MAX_SIZE_T;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return (released != 0)? 1 : 0;
++}
+
++/* ---------------------------- malloc support --------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* allocate a large request from the best fitting chunk in a treebin */
++static void* tmalloc_large(mstate m, size_t nb) {
++ tchunkptr v = 0;
++ size_t rsize = -nb; /* Unsigned negation */
++ tchunkptr t;
++ bindex_t idx;
++ compute_tree_index(nb, idx);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if ((t = *treebin_at(m, idx)) != 0) {
++ /* Traverse tree for this bin looking for node with size == nb */
++ size_t sizebits = nb << leftshift_for_tree_index(idx);
++ tchunkptr rst = 0; /* The deepest untaken right subtree */
++ for (;;) {
++ tchunkptr rt;
++ size_t trem = chunksize(t) - nb;
++ if (trem < rsize) {
++ v = t;
++ if ((rsize = trem) == 0)
++ break;
++ }
++ rt = t->child[1];
++ t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
++ if (rt != 0 && rt != t)
++ rst = rt;
++ if (t == 0) {
++ t = rst; /* set t to least subtree holding sizes > nb */
++ break;
++ }
++ sizebits <<= 1;
++ }
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
++ binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
++ if (leftbits != 0) {
++ bindex_t i;
++ binmap_t leastbit = least_bit(leftbits);
++ compute_bit2idx(leastbit, i);
++ t = *treebin_at(m, i);
++ }
++ }
+
++ while (t != 0) { /* find smallest of tree or subtree */
++ size_t trem = chunksize(t) - nb;
++ if (trem < rsize) {
++ rsize = trem;
++ v = t;
++ }
++ t = leftmost_child(t);
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* If dv is a better fit, return 0 so malloc will use it */
++ if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
++ if (RTCHECK(ok_address(m, v))) { /* split */
++ mchunkptr r = chunk_plus_offset(v, nb);
++ assert(chunksize(v) == rsize + nb);
++ if (RTCHECK(ok_next(v, r))) {
++ unlink_large_chunk(m, v);
++ if (rsize < MIN_CHUNK_SIZE)
++ set_inuse_and_pinuse(m, v, (rsize + nb));
++ else {
++ set_size_and_pinuse_of_inuse_chunk(m, v, nb);
++ set_size_and_pinuse_of_free_chunk(r, rsize);
++ insert_chunk(m, r, rsize);
++ }
++ return chunk2mem(v);
++ }
++ }
++ CORRUPTION_ERROR_ACTION(m);
++ }
++ return 0;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* allocate a small request from the best fitting chunk in a treebin */
++static void* tmalloc_small(mstate m, size_t nb) {
++ tchunkptr t, v;
++ size_t rsize;
++ bindex_t i;
++ binmap_t leastbit = least_bit(m->treemap);
++ compute_bit2idx(leastbit, i);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ v = t = *treebin_at(m, i);
++ rsize = chunksize(t) - nb;
+
++ while ((t = leftmost_child(t)) != 0) {
++ size_t trem = chunksize(t) - nb;
++ if (trem < rsize) {
++ rsize = trem;
++ v = t;
++ }
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (RTCHECK(ok_address(m, v))) {
++ mchunkptr r = chunk_plus_offset(v, nb);
++ assert(chunksize(v) == rsize + nb);
++ if (RTCHECK(ok_next(v, r))) {
++ unlink_large_chunk(m, v);
++ if (rsize < MIN_CHUNK_SIZE)
++ set_inuse_and_pinuse(m, v, (rsize + nb));
++ else {
++ set_size_and_pinuse_of_inuse_chunk(m, v, nb);
++ set_size_and_pinuse_of_free_chunk(r, rsize);
++ replace_dv(m, r, rsize);
++ }
++ return chunk2mem(v);
++ }
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ CORRUPTION_ERROR_ACTION(m);
++ return 0;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++/* --------------------------- realloc support --------------------------- */
+
++static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
++ if (bytes >= MAX_REQUEST) {
++ MALLOC_FAILURE_ACTION;
++ return 0;
++ }
++ if (!PREACTION(m)) {
++ mchunkptr oldp = mem2chunk(oldmem);
++ size_t oldsize = chunksize(oldp);
++ mchunkptr next = chunk_plus_offset(oldp, oldsize);
++ mchunkptr newp = 0;
++ void* extra = 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* Try to either shrink or extend into top. Else malloc-copy-free */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
++ ok_next(oldp, next) && ok_pinuse(next))) {
++ size_t nb = request2size(bytes);
++ if (is_mmapped(oldp))
++ newp = mmap_resize(m, oldp, nb);
++ else if (oldsize >= nb) { /* already big enough */
++ size_t rsize = oldsize - nb;
++ newp = oldp;
++ if (rsize >= MIN_CHUNK_SIZE) {
++ mchunkptr remainder = chunk_plus_offset(newp, nb);
++ set_inuse(m, newp, nb);
++ set_inuse(m, remainder, rsize);
++ extra = chunk2mem(remainder);
++ }
++ }
++ else if (next == m->top && oldsize + m->topsize > nb) {
++ /* Expand into top */
++ size_t newsize = oldsize + m->topsize;
++ size_t newtopsize = newsize - nb;
++ mchunkptr newtop = chunk_plus_offset(oldp, nb);
++ set_inuse(m, oldp, nb);
++ newtop->head = newtopsize |PINUSE_BIT;
++ m->top = newtop;
++ m->topsize = newtopsize;
++ newp = oldp;
++ }
++ }
++ else {
++ USAGE_ERROR_ACTION(m, oldmem);
++ POSTACTION(m);
++ return 0;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ POSTACTION(m);
+
++ if (newp != 0) {
++ if (extra != 0) {
++ internal_free(m, extra);
++ }
++ check_inuse_chunk(m, newp);
++ return chunk2mem(newp);
++ }
++ else {
++ void* newmem = internal_malloc(m, bytes);
++ if (newmem != 0) {
++ size_t oc = oldsize - overhead_for(oldp);
++ memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
++ internal_free(m, oldmem);
++ }
++ return newmem;
++ }
++ }
++ return 0;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* --------------------------- memalign support -------------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
++ if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */
++ return internal_malloc(m, bytes);
++ if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
++ alignment = MIN_CHUNK_SIZE;
++ if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
++ size_t a = MALLOC_ALIGNMENT << 1;
++ while (a < alignment) a <<= 1;
++ alignment = a;
++ }
++
++ if (bytes >= MAX_REQUEST - alignment) {
++ if (m != 0) { /* Test isn't needed but avoids compiler warning */
++ MALLOC_FAILURE_ACTION;
++ }
++ }
++ else {
++ size_t nb = request2size(bytes);
++ size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
++ char* mem = (char*)internal_malloc(m, req);
++ if (mem != 0) {
++ void* leader = 0;
++ void* trailer = 0;
++ mchunkptr p = mem2chunk(mem);
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (PREACTION(m)) return 0;
++ if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
++ /*
++ Find an aligned spot inside chunk. Since we need to give
++ back leading space in a chunk of at least MIN_CHUNK_SIZE, if
++ the first calculation places us at a spot with less than
++ MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
++ We've allocated enough total room so that this is always
++ possible.
++ */
++ char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
++ alignment -
++ SIZE_T_ONE)) &
++ -alignment));
++ char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
++ br : br+alignment;
++ mchunkptr newp = (mchunkptr)pos;
++ size_t leadsize = pos - (char*)(p);
++ size_t newsize = chunksize(p) - leadsize;
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
++ newp->prev_foot = p->prev_foot + leadsize;
++ newp->head = (newsize|CINUSE_BIT);
++ }
++ else { /* Otherwise, give back leader, use the rest */
++ set_inuse(m, newp, newsize);
++ set_inuse(m, p, leadsize);
++ leader = chunk2mem(p);
++ }
++ p = newp;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ /* Give back spare room at the end */
++ if (!is_mmapped(p)) {
++ size_t size = chunksize(p);
++ if (size > nb + MIN_CHUNK_SIZE) {
++ size_t remainder_size = size - nb;
++ mchunkptr remainder = chunk_plus_offset(p, nb);
++ set_inuse(m, p, nb);
++ set_inuse(m, remainder, remainder_size);
++ trailer = chunk2mem(remainder);
++ }
++ }
+
++ assert (chunksize(p) >= nb);
++ assert((((size_t)(chunk2mem(p))) % alignment) == 0);
++ check_inuse_chunk(m, p);
++ POSTACTION(m);
++ if (leader != 0) {
++ internal_free(m, leader);
++ }
++ if (trailer != 0) {
++ internal_free(m, trailer);
++ }
++ return chunk2mem(p);
++ }
++ }
++ return 0;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/* ------------------------ comalloc/coalloc support --------------------- */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static void** ialloc(mstate m,
++ size_t n_elements,
++ size_t* sizes,
++ int opts,
++ void* chunks[]) {
++ /*
++ This provides common support for independent_X routines, handling
++ all of the combinations that can result.
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ The opts arg has:
++ bit 0 set if all elements are same size (using sizes[0])
++ bit 1 set if elements should be zeroed
++ */
+
++ size_t element_size; /* chunksize of each element, if all same */
++ size_t contents_size; /* total size of elements */
++ size_t array_size; /* request size of pointer array */
++ void* mem; /* malloced aggregate space */
++ mchunkptr p; /* corresponding chunk */
++ size_t remainder_size; /* remaining bytes while splitting */
++ void** marray; /* either "chunks" or malloced ptr array */
++ mchunkptr array_chunk; /* chunk for malloced ptr array */
++ flag_t was_enabled; /* to disable mmap */
++ size_t size;
++ size_t i;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* compute array length, if needed */
++ if (chunks != 0) {
++ if (n_elements == 0)
++ return chunks; /* nothing to do */
++ marray = chunks;
++ array_size = 0;
++ }
++ else {
++ /* if empty req, must still return chunk representing empty array */
++ if (n_elements == 0)
++ return (void**)internal_malloc(m, 0);
++ marray = 0;
++ array_size = request2size(n_elements * (sizeof(void*)));
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ /* compute total element size */
++ if (opts & 0x1) { /* all-same-size */
++ element_size = request2size(*sizes);
++ contents_size = n_elements * element_size;
++ }
++ else { /* add up all the sizes */
++ element_size = 0;
++ contents_size = 0;
++ for (i = 0; i != n_elements; ++i)
++ contents_size += request2size(sizes[i]);
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ size = contents_size + array_size;
+
++ /*
++ Allocate the aggregate chunk. First disable direct-mmapping so
++ malloc won't use it, since we would not be able to later
++ free/realloc space internal to a segregated mmap region.
++ */
++ was_enabled = use_mmap(m);
++ disable_mmap(m);
++ mem = internal_malloc(m, size - CHUNK_OVERHEAD);
++ if (was_enabled)
++ enable_mmap(m);
++ if (mem == 0)
++ return 0;
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (PREACTION(m)) return 0;
++ p = mem2chunk(mem);
++ remainder_size = chunksize(p);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ assert(!is_mmapped(p));
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (opts & 0x2) { /* optionally clear the elements */
++ memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
++ }
+
++ /* If not provided, allocate the pointer array as final part of chunk */
++ if (marray == 0) {
++ size_t array_chunk_size;
++ array_chunk = chunk_plus_offset(p, contents_size);
++ array_chunk_size = remainder_size - contents_size;
++ marray = (void**) (chunk2mem(array_chunk));
++ set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
++ remainder_size = contents_size;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ /* split out elements */
++ for (i = 0; ; ++i) {
++ marray[i] = chunk2mem(p);
++ if (i != n_elements-1) {
++ if (element_size != 0)
++ size = element_size;
++ else
++ size = request2size(sizes[i]);
++ remainder_size -= size;
++ set_size_and_pinuse_of_inuse_chunk(m, p, size);
++ p = chunk_plus_offset(p, size);
++ }
++ else { /* the final element absorbs any overallocation slop */
++ set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
++ break;
++ }
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++#if DEBUG
++ if (marray != chunks) {
++ /* final element must have exactly exhausted chunk */
++ if (element_size != 0) {
++ assert(remainder_size == element_size);
++ }
++ else {
++ assert(remainder_size == request2size(sizes[i]));
++ }
++ check_inuse_chunk(m, mem2chunk(marray));
++ }
++ for (i = 0; i != n_elements; ++i)
++ check_inuse_chunk(m, mem2chunk(marray[i]));
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#endif /* DEBUG */
+
++ POSTACTION(m);
++ return marray;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++/* -------------------------- public routines ---------------------------- */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if !ONLY_MSPACES
+
++void* dlmalloc(size_t bytes) {
++ /*
++ Basic algorithm:
++ If a small request (< 256 bytes minus per-chunk overhead):
++ 1. If one exists, use a remainderless chunk in associated smallbin.
++ (Remainderless means that there are too few excess bytes to
++ represent as a chunk.)
++ 2. If it is big enough, use the dv chunk, which is normally the
++ chunk adjacent to the one used for the most recent small request.
++ 3. If one exists, split the smallest available chunk in a bin,
++ saving remainder in dv.
++ 4. If it is big enough, use the top chunk.
++ 5. If available, get memory from system and use it
++ Otherwise, for a large request:
++ 1. Find the smallest available binned chunk that fits, and use it
++ if it is better fitting than dv chunk, splitting if necessary.
++ 2. If better fitting than any binned chunk, use the dv chunk.
++ 3. If it is big enough, use the top chunk.
++ 4. If request size >= mmap threshold, try to directly mmap this chunk.
++ 5. If available, get memory from system and use it
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ The ugly goto's here ensure that postaction occurs along all paths.
++ */
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ if (!PREACTION(gm)) {
++ void* mem;
++ size_t nb;
++ if (bytes <= MAX_SMALL_REQUEST) {
++ bindex_t idx;
++ binmap_t smallbits;
++ nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
++ idx = small_index(nb);
++ smallbits = gm->smallmap >> idx;
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
++ mchunkptr b, p;
++ idx += ~smallbits & 1; /* Uses next bin if idx empty */
++ b = smallbin_at(gm, idx);
++ p = b->fd;
++ assert(chunksize(p) == small_index2size(idx));
++ unlink_first_small_chunk(gm, b, p, idx);
++ set_inuse_and_pinuse(gm, p, small_index2size(idx));
++ mem = chunk2mem(p);
++ check_malloced_chunk(gm, mem, nb);
++ goto postaction;
++ }
+
++ else if (nb > gm->dvsize) {
++ if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
++ mchunkptr b, p, r;
++ size_t rsize;
++ bindex_t i;
++ binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
++ binmap_t leastbit = least_bit(leftbits);
++ compute_bit2idx(leastbit, i);
++ b = smallbin_at(gm, i);
++ p = b->fd;
++ assert(chunksize(p) == small_index2size(i));
++ unlink_first_small_chunk(gm, b, p, i);
++ rsize = small_index2size(i) - nb;
++ /* Fit here cannot be remainderless if 4byte sizes */
++ if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
++ set_inuse_and_pinuse(gm, p, small_index2size(i));
++ else {
++ set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
++ r = chunk_plus_offset(p, nb);
++ set_size_and_pinuse_of_free_chunk(r, rsize);
++ replace_dv(gm, r, rsize);
++ }
++ mem = chunk2mem(p);
++ check_malloced_chunk(gm, mem, nb);
++ goto postaction;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
++ check_malloced_chunk(gm, mem, nb);
++ goto postaction;
++ }
++ }
++ }
++ else if (bytes >= MAX_REQUEST)
++ nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
++ else {
++ nb = pad_request(bytes);
++ if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
++ check_malloced_chunk(gm, mem, nb);
++ goto postaction;
++ }
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (nb <= gm->dvsize) {
++ size_t rsize = gm->dvsize - nb;
++ mchunkptr p = gm->dv;
++ if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
++ mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
++ gm->dvsize = rsize;
++ set_size_and_pinuse_of_free_chunk(r, rsize);
++ set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
++ }
++ else { /* exhaust dv */
++ size_t dvs = gm->dvsize;
++ gm->dvsize = 0;
++ gm->dv = 0;
++ set_inuse_and_pinuse(gm, p, dvs);
++ }
++ mem = chunk2mem(p);
++ check_malloced_chunk(gm, mem, nb);
++ goto postaction;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ else if (nb < gm->topsize) { /* Split top */
++ size_t rsize = gm->topsize -= nb;
++ mchunkptr p = gm->top;
++ mchunkptr r = gm->top = chunk_plus_offset(p, nb);
++ r->head = rsize | PINUSE_BIT;
++ set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
++ mem = chunk2mem(p);
++ check_top_chunk(gm, gm->top);
++ check_malloced_chunk(gm, mem, nb);
++ goto postaction;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ mem = sys_alloc(gm, nb);
+
++ postaction:
++ POSTACTION(gm);
++ return mem;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ return 0;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++void dlfree(void* mem) {
++ /*
++ Consolidate freed chunks with preceding or succeeding bordering
++ free chunks, if they exist, and then place in a bin. Intermixed
++ with special cases for top, dv, mmapped chunks, and usage errors.
++ */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (mem != 0) {
++ mchunkptr p = mem2chunk(mem);
++#if FOOTERS
++ mstate fm = get_mstate_for(p);
++ if (!ok_magic(fm)) {
++ USAGE_ERROR_ACTION(fm, p);
++ return;
++ }
++#else /* FOOTERS */
++#define fm gm
++#endif /* FOOTERS */
++ if (!PREACTION(fm)) {
++ check_inuse_chunk(fm, p);
++ if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
++ size_t psize = chunksize(p);
++ mchunkptr next = chunk_plus_offset(p, psize);
++ if (!pinuse(p)) {
++ size_t prevsize = p->prev_foot;
++ if ((prevsize & IS_MMAPPED_BIT) != 0) {
++ prevsize &= ~IS_MMAPPED_BIT;
++ psize += prevsize + MMAP_FOOT_PAD;
++ if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
++ fm->footprint -= psize;
++ goto postaction;
++ }
++ else {
++ mchunkptr prev = chunk_minus_offset(p, prevsize);
++ psize += prevsize;
++ p = prev;
++ if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
++ if (p != fm->dv) {
++ unlink_chunk(fm, p, prevsize);
++ }
++ else if ((next->head & INUSE_BITS) == INUSE_BITS) {
++ fm->dvsize = psize;
++ set_free_with_pinuse(p, psize, next);
++ goto postaction;
++ }
++ }
++ else
++ goto erroraction;
++ }
++ }
+
++ if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
++ if (!cinuse(next)) { /* consolidate forward */
++ if (next == fm->top) {
++ size_t tsize = fm->topsize += psize;
++ fm->top = p;
++ p->head = tsize | PINUSE_BIT;
++ if (p == fm->dv) {
++ fm->dv = 0;
++ fm->dvsize = 0;
++ }
++ if (should_trim(fm, tsize))
++ sys_trim(fm, 0);
++ goto postaction;
++ }
++ else if (next == fm->dv) {
++ size_t dsize = fm->dvsize += psize;
++ fm->dv = p;
++ set_size_and_pinuse_of_free_chunk(p, dsize);
++ goto postaction;
++ }
++ else {
++ size_t nsize = chunksize(next);
++ psize += nsize;
++ unlink_chunk(fm, next, nsize);
++ set_size_and_pinuse_of_free_chunk(p, psize);
++ if (p == fm->dv) {
++ fm->dvsize = psize;
++ goto postaction;
++ }
++ }
++ }
++ else
++ set_free_with_pinuse(p, psize, next);
++ insert_chunk(fm, p, psize);
++ check_free_chunk(fm, p);
++ goto postaction;
++ }
++ }
++ erroraction:
++ USAGE_ERROR_ACTION(fm, p);
++ postaction:
++ POSTACTION(fm);
++ }
++ }
++#if !FOOTERS
++#undef fm
++#endif /* FOOTERS */
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++void* dlcalloc(size_t n_elements, size_t elem_size) {
++ void* mem;
++ size_t req = 0;
++ if (n_elements != 0) {
++ req = n_elements * elem_size;
++ if (((n_elements | elem_size) & ~(size_t)0xffff) &&
++ (req / n_elements != elem_size))
++ req = MAX_SIZE_T; /* force downstream failure on overflow */
++ }
++ mem = dlmalloc(req);
++ if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
++ memset(mem, 0, req);
++ return mem;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++void* dlrealloc(void* oldmem, size_t bytes) {
++ if (oldmem == 0)
++ return dlmalloc(bytes);
++#ifdef REALLOC_ZERO_BYTES_FREES
++ if (bytes == 0) {
++ dlfree(oldmem);
++ return 0;
++ }
++#endif /* REALLOC_ZERO_BYTES_FREES */
++ else {
++#if ! FOOTERS
++ mstate m = gm;
++#else /* FOOTERS */
++ mstate m = get_mstate_for(mem2chunk(oldmem));
++ if (!ok_magic(m)) {
++ USAGE_ERROR_ACTION(m, oldmem);
++ return 0;
++ }
++#endif /* FOOTERS */
++ return internal_realloc(m, oldmem, bytes);
++ }
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++void* dlmemalign(size_t alignment, size_t bytes) {
++ return internal_memalign(gm, alignment, bytes);
++}
+
++void** dlindependent_calloc(size_t n_elements, size_t elem_size,
++ void* chunks[]) {
++ size_t sz = elem_size; /* serves as 1-element array */
++ return ialloc(gm, n_elements, &sz, 3, chunks);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
++ void* chunks[]) {
++ return ialloc(gm, n_elements, sizes, 0, chunks);
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++void* dlvalloc(size_t bytes) {
++ size_t pagesz;
++ init_mparams();
++ pagesz = mparams.page_size;
++ return dlmemalign(pagesz, bytes);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++void* dlpvalloc(size_t bytes) {
++ size_t pagesz;
++ init_mparams();
++ pagesz = mparams.page_size;
++ return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
++}
+
++int dlmalloc_trim(size_t pad) {
++ int result = 0;
++ if (!PREACTION(gm)) {
++ result = sys_trim(gm, pad);
++ POSTACTION(gm);
++ }
++ return result;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++size_t dlmalloc_footprint(void) {
++ return gm->footprint;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++size_t dlmalloc_max_footprint(void) {
++ return gm->max_footprint;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#if !NO_MALLINFO
++struct mallinfo dlmallinfo(void) {
++ return internal_mallinfo(gm);
++}
++#endif /* NO_MALLINFO */
+
++void dlmalloc_stats() {
++ internal_malloc_stats(gm);
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++size_t dlmalloc_usable_size(void* mem) {
++ if (mem != 0) {
++ mchunkptr p = mem2chunk(mem);
++ if (cinuse(p))
++ return chunksize(p) - overhead_for(p);
++ }
++ return 0;
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++int dlmallopt(int param_number, int value) {
++ return change_mparam(param_number, value);
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++#endif /* !ONLY_MSPACES */
+
++/* ----------------------------- user mspaces ---------------------------- */
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++#if MSPACES
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++static mstate init_user_mstate(char* tbase, size_t tsize) {
++ size_t msize = pad_request(sizeof(struct malloc_state));
++ mchunkptr mn;
++ mchunkptr msp = align_as_chunk(tbase);
++ mstate m = (mstate)(chunk2mem(msp));
++ memset(m, 0, msize);
++ INITIAL_LOCK(&m->mutex);
++ msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
++ m->seg.base = m->least_addr = tbase;
++ m->seg.size = m->footprint = m->max_footprint = tsize;
++ m->magic = mparams.magic;
++ m->mflags = mparams.default_mflags;
++ disable_contiguous(m);
++ init_bins(m);
++ mn = next_chunk(mem2chunk(m));
++ init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
++ check_top_chunk(m, m->top);
++ return m;
++}
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++mspace create_mspace(size_t capacity, int locked) {
++ mstate m = 0;
++ size_t msize = pad_request(sizeof(struct malloc_state));
++ init_mparams(); /* Ensure pagesize etc initialized */
+
++ if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
++ size_t rs = ((capacity == 0)? mparams.granularity :
++ (capacity + TOP_FOOT_SIZE + msize));
++ size_t tsize = granularity_align(rs);
++ char* tbase = (char*)(CALL_MMAP(tsize));
++ if (tbase != CMFAIL) {
++ m = init_user_mstate(tbase, tsize);
++ set_segment_flags(&m->seg, IS_MMAPPED_BIT);
++ set_lock(m, locked);
++ }
++ }
++ return (mspace)m;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
++ mstate m = 0;
++ size_t msize = pad_request(sizeof(struct malloc_state));
++ init_mparams(); /* Ensure pagesize etc initialized */
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (capacity > msize + TOP_FOOT_SIZE &&
++ capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
++ m = init_user_mstate((char*)base, capacity);
++ set_segment_flags(&m->seg, EXTERN_BIT);
++ set_lock(m, locked);
++ }
++ return (mspace)m;
++}
+
++size_t destroy_mspace(mspace msp) {
++ size_t freed = 0;
++ mstate ms = (mstate)msp;
++ if (ok_magic(ms)) {
++ msegmentptr sp = &ms->seg;
++ while (sp != 0) {
++ char* base = sp->base;
++ size_t size = sp->size;
++ flag_t flag = get_segment_flags(sp);
++ sp = sp->next;
++ if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
++ CALL_MUNMAP(base, size) == 0)
++ freed += size;
++ }
++ }
++ else {
++ USAGE_ERROR_ACTION(ms,ms);
++ }
++ return freed;
++}
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++/*
++ mspace versions of routines are near-clones of the global
++ versions. This is not so nice but better than the alternatives.
++*/
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++void* mspace_malloc(mspace msp, size_t bytes) {
++ mstate ms = (mstate)msp;
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ return 0;
++ }
++ if (!PREACTION(ms)) {
++ void* mem;
++ size_t nb;
++ if (bytes <= MAX_SMALL_REQUEST) {
++ bindex_t idx;
++ binmap_t smallbits;
++ nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
++ idx = small_index(nb);
++ smallbits = ms->smallmap >> idx;
+
++ if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
++ mchunkptr b, p;
++ idx += ~smallbits & 1; /* Uses next bin if idx empty */
++ b = smallbin_at(ms, idx);
++ p = b->fd;
++ assert(chunksize(p) == small_index2size(idx));
++ unlink_first_small_chunk(ms, b, p, idx);
++ set_inuse_and_pinuse(ms, p, small_index2size(idx));
++ mem = chunk2mem(p);
++ check_malloced_chunk(ms, mem, nb);
++ goto postaction;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ else if (nb > ms->dvsize) {
++ if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
++ mchunkptr b, p, r;
++ size_t rsize;
++ bindex_t i;
++ binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
++ binmap_t leastbit = least_bit(leftbits);
++ compute_bit2idx(leastbit, i);
++ b = smallbin_at(ms, i);
++ p = b->fd;
++ assert(chunksize(p) == small_index2size(i));
++ unlink_first_small_chunk(ms, b, p, i);
++ rsize = small_index2size(i) - nb;
++ /* Fit here cannot be remainderless if 4byte sizes */
++ if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
++ set_inuse_and_pinuse(ms, p, small_index2size(i));
++ else {
++ set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
++ r = chunk_plus_offset(p, nb);
++ set_size_and_pinuse_of_free_chunk(r, rsize);
++ replace_dv(ms, r, rsize);
++ }
++ mem = chunk2mem(p);
++ check_malloced_chunk(ms, mem, nb);
++ goto postaction;
++ }
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
++ check_malloced_chunk(ms, mem, nb);
++ goto postaction;
++ }
++ }
++ }
++ else if (bytes >= MAX_REQUEST)
++ nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
++ else {
++ nb = pad_request(bytes);
++ if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
++ check_malloced_chunk(ms, mem, nb);
++ goto postaction;
++ }
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ if (nb <= ms->dvsize) {
++ size_t rsize = ms->dvsize - nb;
++ mchunkptr p = ms->dv;
++ if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
++ mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
++ ms->dvsize = rsize;
++ set_size_and_pinuse_of_free_chunk(r, rsize);
++ set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
++ }
++ else { /* exhaust dv */
++ size_t dvs = ms->dvsize;
++ ms->dvsize = 0;
++ ms->dv = 0;
++ set_inuse_and_pinuse(ms, p, dvs);
++ }
++ mem = chunk2mem(p);
++ check_malloced_chunk(ms, mem, nb);
++ goto postaction;
++ }
+
++ else if (nb < ms->topsize) { /* Split top */
++ size_t rsize = ms->topsize -= nb;
++ mchunkptr p = ms->top;
++ mchunkptr r = ms->top = chunk_plus_offset(p, nb);
++ r->head = rsize | PINUSE_BIT;
++ set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
++ mem = chunk2mem(p);
++ check_top_chunk(ms, ms->top);
++ check_malloced_chunk(ms, mem, nb);
++ goto postaction;
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ mem = sys_alloc(ms, nb);
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
++ postaction:
++ POSTACTION(ms);
++ return mem;
++ }
+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
++ return 0;
++}
+
++void mspace_free(mspace msp, void* mem) {
++ if (mem != 0) {
++ mchunkptr p = mem2chunk(mem);
++#if FOOTERS
++ mstate fm = get_mstate_for(p);
++#else /* FOOTERS */
++ mstate fm = (mstate)msp;
++#endif /* FOOTERS */
++ if (!ok_magic(fm)) {
++ USAGE_ERROR_ACTION(fm, p);
++ return;
++ }
++ if (!PREACTION(fm)) {
++ check_inuse_chunk(fm, p);
++ if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
++ size_t psize = chunksize(p);
++ mchunkptr next = chunk_plus_offset(p, psize);
++ if (!pinuse(p)) {
++ size_t prevsize = p->prev_foot;
++ if ((prevsize & IS_MMAPPED_BIT) != 0) {
++ prevsize &= ~IS_MMAPPED_BIT;
++ psize += prevsize + MMAP_FOOT_PAD;
++ if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
++ fm->footprint -= psize;
++ goto postaction;
++ }
++ else {
++ mchunkptr prev = chunk_minus_offset(p, prevsize);
++ psize += prevsize;
++ p = prev;
++ if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
++ if (p != fm->dv) {
++ unlink_chunk(fm, p, prevsize);
++ }
++ else if ((next->head & INUSE_BITS) == INUSE_BITS) {
++ fm->dvsize = psize;
++ set_free_with_pinuse(p, psize, next);
++ goto postaction;
++ }
++ }
++ else
++ goto erroraction;
++ }
++ }
+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
++ if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
++ if (!cinuse(next)) { /* consolidate forward */
++ if (next == fm->top) {
++ size_t tsize = fm->topsize += psize;
++ fm->top = p;
++ p->head = tsize | PINUSE_BIT;
++ if (p == fm->dv) {
++ fm->dv = 0;
++ fm->dvsize = 0;
++ }
++ if (should_trim(fm, tsize))
++ sys_trim(fm, 0);
++ goto postaction;
++ }
++ else if (next == fm->dv) {
++ size_t dsize = fm->dvsize += psize;
++ fm->dv = p;
++ set_size_and_pinuse_of_free_chunk(p, dsize);
++ goto postaction;
++ }
++ else {
++ size_t nsize = chunksize(next);
++ psize += nsize;
++ unlink_chunk(fm, next, nsize);
++ set_size_and_pinuse_of_free_chunk(p, psize);
++ if (p == fm->dv) {
++ fm->dvsize = psize;
++ goto postaction;
++ }
++ }
++ }
++ else
++ set_free_with_pinuse(p, psize, next);
++ insert_chunk(fm, p, psize);
++ check_free_chunk(fm, p);
++ goto postaction;
++ }
++ }
++ erroraction:
++ USAGE_ERROR_ACTION(fm, p);
++ postaction:
++ POSTACTION(fm);
++ }
++ }
++}
+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+ // trampoline
-+ // Save to stack
-+ stmfd sp!, {r0-r3}
-+
-+ // Load the context argument from the config page.
-+ // This places the first usable config value at _ffi_closure_trampoline_table-4080
-+ // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
-+ ldr r0, [pc, #-4092]
-+
-+ // Load the jump address from the config page.
-+ ldr pc, [pc, #-4092]
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/closures.c modified/Modules/_ctypes/libffi_ios/closures.c
---- orig/Modules/_ctypes/libffi_ios/closures.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/closures.c 2015-04-26 08:17:59.000000000 +0800
-@@ -0,0 +1,688 @@
-+/* -----------------------------------------------------------------------
-+ closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
-+ Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
-+ Copyright (c) 2011 Plausible Labs Cooperative, Inc.
-+
-+ Code to allocate and deallocate memory for closures.
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
-+
-+#if defined __linux__ && !defined _GNU_SOURCE
-+#define _GNU_SOURCE 1
-+#endif
-+
-+#include
-+#include
-+
-+#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
-+# if __gnu_linux__ && !defined(__ANDROID__)
-+/* This macro indicates it may be forbidden to map anonymous memory
-+ with both write and execute permission. Code compiled when this
-+ option is defined will attempt to map such pages once, but if it
-+ fails, it falls back to creating a temporary file in a writable and
-+ executable filesystem and mapping pages from it into separate
-+ locations in the virtual memory space, one location writable and
-+ another executable. */
-+# define FFI_MMAP_EXEC_WRIT 1
-+# define HAVE_MNTENT 1
-+# endif
-+# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
-+/* Windows systems may have Data Execution Protection (DEP) enabled,
-+ which requires the use of VirtualMalloc/VirtualFree to alloc/free
-+ executable memory. */
-+# define FFI_MMAP_EXEC_WRIT 1
-+# endif
-+#endif
-+
-+#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
-+# ifdef __linux__
-+/* When defined to 1 check for SELinux and if SELinux is active,
-+ don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
-+ might cause audit messages. */
-+# define FFI_MMAP_EXEC_SELINUX 1
-+# endif
-+#endif
-+
-+#if FFI_CLOSURES
-+
-+# if FFI_EXEC_TRAMPOLINE_TABLE
-+
-+// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations.
-+
-+# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
-+
-+#define USE_LOCKS 1
-+#define USE_DL_PREFIX 1
-+#ifdef __GNUC__
-+#ifndef USE_BUILTIN_FFS
-+#define USE_BUILTIN_FFS 1
-+#endif
-+#endif
-+
-+/* We need to use mmap, not sbrk. */
-+#define HAVE_MORECORE 0
-+
-+/* We could, in theory, support mremap, but it wouldn't buy us anything. */
-+#define HAVE_MREMAP 0
-+
-+/* We have no use for this, so save some code and data. */
-+#define NO_MALLINFO 1
-+
-+/* We need all allocations to be in regular segments, otherwise we
-+ lose track of the corresponding code address. */
-+#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
-+
-+/* Don't allocate more than a page unless needed. */
-+#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
-+
-+#if FFI_CLOSURE_TEST
-+/* Don't release single pages, to avoid a worst-case scenario of
-+ continuously allocating and releasing single pages, but release
-+ pairs of pages, which should do just as well given that allocations
-+ are likely to be small. */
-+#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
-+#endif
-+
-+#include
-+#include
-+#include
-+#include
-+#ifndef _MSC_VER
-+#include
-+#endif
-+#include
-+#include
-+#if !defined(X86_WIN32) && !defined(X86_WIN64)
-+#ifdef HAVE_MNTENT
-+#include
-+#endif /* HAVE_MNTENT */
-+#include
-+#include
-+
-+/* We don't want sys/mman.h to be included after we redefine mmap and
-+ dlmunmap. */
-+#include
-+#define LACKS_SYS_MMAN_H 1
-+
-+#if FFI_MMAP_EXEC_SELINUX
-+#include
-+#include
-+
-+static int selinux_enabled = -1;
-+
-+static int
-+selinux_enabled_check (void)
-+{
-+ struct statfs sfs;
-+ FILE *f;
-+ char *buf = NULL;
-+ size_t len = 0;
-+
-+ if (statfs ("/selinux", &sfs) >= 0
-+ && (unsigned int) sfs.f_type == 0xf97cff8cU)
-+ return 1;
-+ f = fopen ("/proc/mounts", "r");
-+ if (f == NULL)
-+ return 0;
-+ while (getline (&buf, &len, f) >= 0)
-+ {
-+ char *p = strchr (buf, ' ');
-+ if (p == NULL)
-+ break;
-+ p = strchr (p + 1, ' ');
-+ if (p == NULL)
-+ break;
-+ if (strncmp (p + 1, "selinuxfs ", 10) == 0)
-+ {
-+ free (buf);
-+ fclose (f);
-+ return 1;
-+ }
-+ }
-+ free (buf);
-+ fclose (f);
-+ return 0;
-+}
-+
-+#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
-+ : (selinux_enabled = selinux_enabled_check ()))
-+
-+#else
-+
-+#define is_selinux_enabled() 0
-+
-+#endif /* !FFI_MMAP_EXEC_SELINUX */
-+
-+/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
-+#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
-+#include
-+
-+static int emutramp_enabled = -1;
-+
-+static int
-+emutramp_enabled_check (void)
-+{
-+ char *buf = NULL;
-+ size_t len = 0;
-+ FILE *f;
-+ int ret;
-+ f = fopen ("/proc/self/status", "r");
-+ if (f == NULL)
-+ return 0;
-+ ret = 0;
-+
-+ while (getline (&buf, &len, f) != -1)
-+ if (!strncmp (buf, "PaX:", 4))
-+ {
-+ char emutramp;
-+ if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
-+ ret = (emutramp == 'E');
-+ break;
-+ }
-+ free (buf);
-+ fclose (f);
-+ return ret;
-+}
-+
-+#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
-+ : (emutramp_enabled = emutramp_enabled_check ()))
-+#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
-+
-+#elif defined (__CYGWIN__) || defined(__INTERIX)
-+
-+#include
-+
-+/* Cygwin is Linux-like, but not quite that Linux-like. */
-+#define is_selinux_enabled() 0
-+
-+#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
-+
-+#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
-+#define is_emutramp_enabled() 0
-+#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
-+
-+/* Declare all functions defined in dlmalloc.c as static. */
-+static void *dlmalloc(size_t);
-+static void dlfree(void*);
-+static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
-+static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
-+static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
-+static void *dlvalloc(size_t) MAYBE_UNUSED;
-+static int dlmallopt(int, int) MAYBE_UNUSED;
-+static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
-+static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
-+static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
-+static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
-+static void *dlpvalloc(size_t) MAYBE_UNUSED;
-+static int dlmalloc_trim(size_t) MAYBE_UNUSED;
-+static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
-+static void dlmalloc_stats(void) MAYBE_UNUSED;
-+
-+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
-+/* Use these for mmap and munmap within dlmalloc.c. */
-+static void *dlmmap(void *, size_t, int, int, int, off_t);
-+static int dlmunmap(void *, size_t);
-+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
-+
-+#define mmap dlmmap
-+#define munmap dlmunmap
-+
-+#include "dlmalloc.c"
-+
-+#undef mmap
-+#undef munmap
-+
-+#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
-+
-+/* A mutex used to synchronize access to *exec* variables in this file. */
-+static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
-+
-+/* A file descriptor of a temporary file from which we'll map
-+ executable pages. */
-+static int execfd = -1;
-+
-+/* The amount of space already allocated from the temporary file. */
-+static size_t execsize = 0;
-+
-+/* Open a temporary file name, and immediately unlink it. */
-+static int
-+open_temp_exec_file_name (char *name, int flags)
-+{
-+ int fd;
-+
-+#ifdef HAVE_MKOSTEMP
-+ fd = mkostemp (name, flags);
-+#else
-+ fd = mkstemp (name);
-+#endif
-+
-+ if (fd != -1)
-+ unlink (name);
-+
-+ return fd;
-+}
-+
-+/* Open a temporary file in the named directory. */
-+static int
-+open_temp_exec_file_dir (const char *dir)
-+{
-+ static const char suffix[] = "/ffiXXXXXX";
-+ int lendir, flags;
-+ char *tempname;
-+#ifdef O_TMPFILE
-+ int fd;
-+#endif
-+
-+#ifdef O_CLOEXEC
-+ flags = O_CLOEXEC;
-+#else
-+ flags = 0;
-+#endif
-+
-+#ifdef O_TMPFILE
-+ fd = open (dir, flags | O_RDWR | O_EXCL | O_TMPFILE, 0700);
-+ /* If the running system does not support the O_TMPFILE flag then retry without it. */
-+ if (fd != -1 || (errno != EINVAL && errno != EISDIR && errno != EOPNOTSUPP)) {
-+ return fd;
-+ } else {
-+ errno = 0;
-+ }
-+#endif
-+
-+ lendir = strlen (dir);
-+ tempname = __builtin_alloca (lendir + sizeof (suffix));
-+
-+ if (!tempname)
-+ return -1;
-+
-+ memcpy (tempname, dir, lendir);
-+ memcpy (tempname + lendir, suffix, sizeof (suffix));
-+
-+ return open_temp_exec_file_name (tempname, flags);
-+}
-+
-+/* Open a temporary file in the directory in the named environment
-+ variable. */
-+static int
-+open_temp_exec_file_env (const char *envvar)
-+{
-+ const char *value = getenv (envvar);
-+
-+ if (!value)
-+ return -1;
-+
-+ return open_temp_exec_file_dir (value);
-+}
-+
-+#ifdef HAVE_MNTENT
-+/* Open a temporary file in an executable and writable mount point
-+ listed in the mounts file. Subsequent calls with the same mounts
-+ keep searching for mount points in the same file. Providing NULL
-+ as the mounts file closes the file. */
-+static int
-+open_temp_exec_file_mnt (const char *mounts)
-+{
-+ static const char *last_mounts;
-+ static FILE *last_mntent;
-+
-+ if (mounts != last_mounts)
-+ {
-+ if (last_mntent)
-+ endmntent (last_mntent);
-+
-+ last_mounts = mounts;
-+
-+ if (mounts)
-+ last_mntent = setmntent (mounts, "r");
-+ else
-+ last_mntent = NULL;
-+ }
-+
-+ if (!last_mntent)
-+ return -1;
-+
-+ for (;;)
-+ {
-+ int fd;
-+ struct mntent mnt;
-+ char buf[MAXPATHLEN * 3];
-+
-+ if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL)
-+ return -1;
-+
-+ if (hasmntopt (&mnt, "ro")
-+ || hasmntopt (&mnt, "noexec")
-+ || access (mnt.mnt_dir, W_OK))
-+ continue;
-+
-+ fd = open_temp_exec_file_dir (mnt.mnt_dir);
-+
-+ if (fd != -1)
-+ return fd;
-+ }
-+}
-+#endif /* HAVE_MNTENT */
-+
-+/* Instructions to look for a location to hold a temporary file that
-+ can be mapped in for execution. */
-+static struct
-+{
-+ int (*func)(const char *);
-+ const char *arg;
-+ int repeat;
-+} open_temp_exec_file_opts[] = {
-+ { open_temp_exec_file_env, "TMPDIR", 0 },
-+ { open_temp_exec_file_dir, "/tmp", 0 },
-+ { open_temp_exec_file_dir, "/var/tmp", 0 },
-+ { open_temp_exec_file_dir, "/dev/shm", 0 },
-+ { open_temp_exec_file_env, "HOME", 0 },
-+#ifdef HAVE_MNTENT
-+ { open_temp_exec_file_mnt, "/etc/mtab", 1 },
-+ { open_temp_exec_file_mnt, "/proc/mounts", 1 },
-+#endif /* HAVE_MNTENT */
-+};
-+
-+/* Current index into open_temp_exec_file_opts. */
-+static int open_temp_exec_file_opts_idx = 0;
-+
-+/* Reset a current multi-call func, then advances to the next entry.
-+ If we're at the last, go back to the first and return nonzero,
-+ otherwise return zero. */
-+static int
-+open_temp_exec_file_opts_next (void)
-+{
-+ if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
-+ open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
-+
-+ open_temp_exec_file_opts_idx++;
-+ if (open_temp_exec_file_opts_idx
-+ == (sizeof (open_temp_exec_file_opts)
-+ / sizeof (*open_temp_exec_file_opts)))
-+ {
-+ open_temp_exec_file_opts_idx = 0;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Return a file descriptor of a temporary zero-sized file in a
-+ writable and executable filesystem. */
-+static int
-+open_temp_exec_file (void)
-+{
-+ int fd;
-+
-+ do
-+ {
-+ fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
-+ (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
-+
-+ if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
-+ || fd == -1)
-+ {
-+ if (open_temp_exec_file_opts_next ())
-+ break;
-+ }
-+ }
-+ while (fd == -1);
-+
-+ return fd;
-+}
-+
-+/* Map in a chunk of memory from the temporary exec file into separate
-+ locations in the virtual memory address space, one writable and one
-+ executable. Returns the address of the writable portion, after
-+ storing an offset to the corresponding executable portion at the
-+ last word of the requested chunk. */
-+static void *
-+dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
-+{
-+ void *ptr;
-+
-+ if (execfd == -1)
-+ {
-+ open_temp_exec_file_opts_idx = 0;
-+ retry_open:
-+ execfd = open_temp_exec_file ();
-+ if (execfd == -1)
-+ return MFAIL;
-+ }
-+
-+ offset = execsize;
-+
-+ if (ftruncate (execfd, offset + length))
-+ return MFAIL;
-+
-+ flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
-+ flags |= MAP_SHARED;
-+
-+ ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
-+ flags, execfd, offset);
-+ if (ptr == MFAIL)
-+ {
-+ if (!offset)
-+ {
-+ close (execfd);
-+ goto retry_open;
-+ }
-+ ftruncate (execfd, offset);
-+ return MFAIL;
-+ }
-+ else if (!offset
-+ && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
-+ open_temp_exec_file_opts_next ();
-+
-+ start = mmap (start, length, prot, flags, execfd, offset);
-+
-+ if (start == MFAIL)
-+ {
-+ munmap (ptr, length);
-+ ftruncate (execfd, offset);
-+ return start;
-+ }
-+
-+ mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
-+
-+ execsize += length;
-+
-+ return start;
-+}
-+
-+/* Map in a writable and executable chunk of memory if possible.
-+ Failing that, fall back to dlmmap_locked. */
-+static void *
-+dlmmap (void *start, size_t length, int prot,
-+ int flags, int fd, off_t offset)
-+{
-+ void *ptr;
-+
-+ assert (start == NULL && length % malloc_getpagesize == 0
-+ && prot == (PROT_READ | PROT_WRITE)
-+ && flags == (MAP_PRIVATE | MAP_ANONYMOUS)
-+ && fd == -1 && offset == 0);
-+
-+#if FFI_CLOSURE_TEST
-+ printf ("mapping in %zi\n", length);
-+#endif
-+
-+ if (execfd == -1 && is_emutramp_enabled ())
-+ {
-+ ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
-+ return ptr;
-+ }
-+
-+ if (execfd == -1 && !is_selinux_enabled ())
-+ {
-+ ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
-+
-+ if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
-+ /* Cool, no need to mess with separate segments. */
-+ return ptr;
-+
-+ /* If MREMAP_DUP is ever introduced and implemented, try mmap
-+ with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
-+ MREMAP_DUP and prot at this point. */
-+ }
-+
-+ if (execsize == 0 || execfd == -1)
-+ {
-+ pthread_mutex_lock (&open_temp_exec_file_mutex);
-+ ptr = dlmmap_locked (start, length, prot, flags, offset);
-+ pthread_mutex_unlock (&open_temp_exec_file_mutex);
-+
-+ return ptr;
-+ }
-+
-+ return dlmmap_locked (start, length, prot, flags, offset);
-+}
-+
-+/* Release memory at the given address, as well as the corresponding
-+ executable page if it's separate. */
-+static int
-+dlmunmap (void *start, size_t length)
-+{
-+ /* We don't bother decreasing execsize or truncating the file, since
-+ we can't quite tell whether we're unmapping the end of the file.
-+ We don't expect frequent deallocation anyway. If we did, we
-+ could locate pages in the file by writing to the pages being
-+ deallocated and checking that the file contents change.
-+ Yuck. */
-+ msegmentptr seg = segment_holding (gm, start);
-+ void *code;
-+
-+#if FFI_CLOSURE_TEST
-+ printf ("unmapping %zi\n", length);
-+#endif
-+
-+ if (seg && (code = add_segment_exec_offset (start, seg)) != start)
-+ {
-+ int ret = munmap (code, length);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return munmap (start, length);
-+}
-+
-+#if FFI_CLOSURE_FREE_CODE
-+/* Return segment holding given code address. */
-+static msegmentptr
-+segment_holding_code (mstate m, char* addr)
-+{
-+ msegmentptr sp = &m->seg;
-+ for (;;) {
-+ if (addr >= add_segment_exec_offset (sp->base, sp)
-+ && addr < add_segment_exec_offset (sp->base, sp) + sp->size)
-+ return sp;
-+ if ((sp = sp->next) == 0)
-+ return 0;
-+ }
-+}
-+#endif
-+
-+#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
-+
-+/* Allocate a chunk of memory with the given size. Returns a pointer
-+ to the writable address, and sets *CODE to the executable
-+ corresponding virtual address. */
-+void *
-+ffi_closure_alloc (size_t size, void **code)
-+{
-+ void *ptr;
-+
-+ if (!code)
-+ return NULL;
-+
-+ ptr = dlmalloc (size);
-+
-+ if (ptr)
-+ {
-+ msegmentptr seg = segment_holding (gm, ptr);
-+
-+ *code = add_segment_exec_offset (ptr, seg);
-+ }
-+
-+ return ptr;
-+}
-+
-+/* Release a chunk of memory allocated with ffi_closure_alloc. If
-+ FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
-+ writable or the executable address given. Otherwise, only the
-+ writable address can be provided here. */
-+void
-+ffi_closure_free (void *ptr)
-+{
-+#if FFI_CLOSURE_FREE_CODE
-+ msegmentptr seg = segment_holding_code (gm, ptr);
-+
-+ if (seg)
-+ ptr = sub_segment_exec_offset (ptr, seg);
-+#endif
-+
-+ dlfree (ptr);
-+}
-+
-+
-+#if FFI_CLOSURE_TEST
-+/* Do some internal sanity testing to make sure allocation and
-+ deallocation of pages are working as intended. */
-+int main ()
-+{
-+ void *p[3];
-+#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
-+#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
-+ GET (0, malloc_getpagesize / 2);
-+ GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
-+ PUT (1);
-+ GET (1, 2 * malloc_getpagesize);
-+ GET (2, malloc_getpagesize / 2);
-+ PUT (1);
-+ PUT (0);
-+ PUT (2);
-+ return 0;
-+}
-+#endif /* FFI_CLOSURE_TEST */
-+# else /* ! FFI_MMAP_EXEC_WRIT */
-+
-+/* On many systems, memory returned by malloc is writable and
-+ executable, so just use it. */
-+
-+#include
-+
-+void *
-+ffi_closure_alloc (size_t size, void **code)
-+{
-+ if (!code)
-+ return NULL;
-+
-+ return *code = malloc (size);
-+}
-+
-+void
-+ffi_closure_free (void *ptr)
-+{
-+ free (ptr);
-+}
-+
-+# endif /* ! FFI_MMAP_EXEC_WRIT */
-+#endif /* FFI_CLOSURES */
-diff -Nru orig/Modules/_ctypes/libffi_ios/dlmalloc.c modified/Modules/_ctypes/libffi_ios/dlmalloc.c
---- orig/Modules/_ctypes/libffi_ios/dlmalloc.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/dlmalloc.c 2015-04-26 09:40:43.000000000 +0800
-@@ -0,0 +1,5161 @@
-+/*
-+ This is a version (aka dlmalloc) of malloc/free/realloc written by
-+ Doug Lea and released to the public domain, as explained at
-+ http://creativecommons.org/licenses/publicdomain. Send questions,
-+ comments, complaints, performance data, etc to dl@cs.oswego.edu
-+
-+* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee)
-+
-+ Note: There may be an updated version of this malloc obtainable at
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc.c
-+ Check before installing!
-+
-+* Quickstart
-+
-+ This library is all in one file to simplify the most common usage:
-+ ftp it, compile it (-O3), and link it into another program. All of
-+ the compile-time options default to reasonable values for use on
-+ most platforms. You might later want to step through various
-+ compile-time and dynamic tuning options.
-+
-+ For convenience, an include file for code using this malloc is at:
-+ ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h
-+ You don't really need this .h file unless you call functions not
-+ defined in your system include files. The .h file contains only the
-+ excerpts from this file needed for using this malloc on ANSI C/C++
-+ systems, so long as you haven't changed compile-time options about
-+ naming and tuning parameters. If you do, then you can create your
-+ own malloc.h that does include all settings by cutting at the point
-+ indicated below. Note that you may already by default be using a C
-+ library containing a malloc that is based on some version of this
-+ malloc (for example in linux). You might still want to use the one
-+ in this file to customize settings or to avoid overheads associated
-+ with library versions.
-+
-+* Vital statistics:
-+
-+ Supported pointer/size_t representation: 4 or 8 bytes
-+ size_t MUST be an unsigned type of the same width as
-+ pointers. (If you are using an ancient system that declares
-+ size_t as a signed type, or need it to be a different width
-+ than pointers, you can use a previous release of this malloc
-+ (e.g. 2.7.2) supporting these.)
-+
-+ Alignment: 8 bytes (default)
-+ This suffices for nearly all current machines and C compilers.
-+ However, you can define MALLOC_ALIGNMENT to be wider than this
-+ if necessary (up to 128bytes), at the expense of using more space.
-+
-+ Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes)
-+ 8 or 16 bytes (if 8byte sizes)
-+ Each malloced chunk has a hidden word of overhead holding size
-+ and status information, and additional cross-check word
-+ if FOOTERS is defined.
-+
-+ Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead)
-+ 8-byte ptrs: 32 bytes (including overhead)
-+
-+ Even a request for zero bytes (i.e., malloc(0)) returns a
-+ pointer to something of the minimum allocatable size.
-+ The maximum overhead wastage (i.e., number of extra bytes
-+ allocated than were requested in malloc) is less than or equal
-+ to the minimum size, except for requests >= mmap_threshold that
-+ are serviced via mmap(), where the worst case wastage is about
-+ 32 bytes plus the remainder from a system page (the minimal
-+ mmap unit); typically 4096 or 8192 bytes.
-+
-+ Security: static-safe; optionally more or less
-+ The "security" of malloc refers to the ability of malicious
-+ code to accentuate the effects of errors (for example, freeing
-+ space that is not currently malloc'ed or overwriting past the
-+ ends of chunks) in code that calls malloc. This malloc
-+ guarantees not to modify any memory locations below the base of
-+ heap, i.e., static variables, even in the presence of usage
-+ errors. The routines additionally detect most improper frees
-+ and reallocs. All this holds as long as the static bookkeeping
-+ for malloc itself is not corrupted by some other means. This
-+ is only one aspect of security -- these checks do not, and
-+ cannot, detect all possible programming errors.
-+
-+ If FOOTERS is defined nonzero, then each allocated chunk
-+ carries an additional check word to verify that it was malloced
-+ from its space. These check words are the same within each
-+ execution of a program using malloc, but differ across
-+ executions, so externally crafted fake chunks cannot be
-+ freed. This improves security by rejecting frees/reallocs that
-+ could corrupt heap memory, in addition to the checks preventing
-+ writes to statics that are always on. This may further improve
-+ security at the expense of time and space overhead. (Note that
-+ FOOTERS may also be worth using with MSPACES.)
-+
-+ By default detected errors cause the program to abort (calling
-+ "abort()"). You can override this to instead proceed past
-+ errors by defining PROCEED_ON_ERROR. In this case, a bad free
-+ has no effect, and a malloc that encounters a bad address
-+ caused by user overwrites will ignore the bad address by
-+ dropping pointers and indices to all known memory. This may
-+ be appropriate for programs that should continue if at all
-+ possible in the face of programming errors, although they may
-+ run out of memory because dropped memory is never reclaimed.
-+
-+ If you don't like either of these options, you can define
-+ CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything
-+ else. And if if you are sure that your program using malloc has
-+ no errors or vulnerabilities, you can define INSECURE to 1,
-+ which might (or might not) provide a small performance improvement.
-+
-+ Thread-safety: NOT thread-safe unless USE_LOCKS defined
-+ When USE_LOCKS is defined, each public call to malloc, free,
-+ etc is surrounded with either a pthread mutex or a win32
-+ spinlock (depending on WIN32). This is not especially fast, and
-+ can be a major bottleneck. It is designed only to provide
-+ minimal protection in concurrent environments, and to provide a
-+ basis for extensions. If you are using malloc in a concurrent
-+ program, consider instead using ptmalloc, which is derived from
-+ a version of this malloc. (See http://www.malloc.de).
-+
-+ System requirements: Any combination of MORECORE and/or MMAP/MUNMAP
-+ This malloc can use unix sbrk or any emulation (invoked using
-+ the CALL_MORECORE macro) and/or mmap/munmap or any emulation
-+ (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system
-+ memory. On most unix systems, it tends to work best if both
-+ MORECORE and MMAP are enabled. On Win32, it uses emulations
-+ based on VirtualAlloc. It also uses common C library functions
-+ like memset.
-+
-+ Compliance: I believe it is compliant with the Single Unix Specification
-+ (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably
-+ others as well.
-+
-+* Overview of algorithms
-+
-+ This is not the fastest, most space-conserving, most portable, or
-+ most tunable malloc ever written. However it is among the fastest
-+ while also being among the most space-conserving, portable and
-+ tunable. Consistent balance across these factors results in a good
-+ general-purpose allocator for malloc-intensive programs.
-+
-+ In most ways, this malloc is a best-fit allocator. Generally, it
-+ chooses the best-fitting existing chunk for a request, with ties
-+ broken in approximately least-recently-used order. (This strategy
-+ normally maintains low fragmentation.) However, for requests less
-+ than 256bytes, it deviates from best-fit when there is not an
-+ exactly fitting available chunk by preferring to use space adjacent
-+ to that used for the previous small request, as well as by breaking
-+ ties in approximately most-recently-used order. (These enhance
-+ locality of series of small allocations.) And for very large requests
-+ (>= 256Kb by default), it relies on system memory mapping
-+ facilities, if supported. (This helps avoid carrying around and
-+ possibly fragmenting memory used only for large chunks.)
-+
-+ All operations (except malloc_stats and mallinfo) have execution
-+ times that are bounded by a constant factor of the number of bits in
-+ a size_t, not counting any clearing in calloc or copying in realloc,
-+ or actions surrounding MORECORE and MMAP that have times
-+ proportional to the number of non-contiguous regions returned by
-+ system allocation routines, which is often just 1.
-+
-+ The implementation is not very modular and seriously overuses
-+ macros. Perhaps someday all C compilers will do as good a job
-+ inlining modular code as can now be done by brute-force expansion,
-+ but now, enough of them seem not to.
-+
-+ Some compilers issue a lot of warnings about code that is
-+ dead/unreachable only on some platforms, and also about intentional
-+ uses of negation on unsigned types. All known cases of each can be
-+ ignored.
-+
-+ For a longer but out of date high-level description, see
-+ http://gee.cs.oswego.edu/dl/html/malloc.html
-+
-+* MSPACES
-+ If MSPACES is defined, then in addition to malloc, free, etc.,
-+ this file also defines mspace_malloc, mspace_free, etc. These
-+ are versions of malloc routines that take an "mspace" argument
-+ obtained using create_mspace, to control all internal bookkeeping.
-+ If ONLY_MSPACES is defined, only these versions are compiled.
-+ So if you would like to use this allocator for only some allocations,
-+ and your system malloc for others, you can compile with
-+ ONLY_MSPACES and then do something like...
-+ static mspace mymspace = create_mspace(0,0); // for example
-+ #define mymalloc(bytes) mspace_malloc(mymspace, bytes)
-+
-+ (Note: If you only need one instance of an mspace, you can instead
-+ use "USE_DL_PREFIX" to relabel the global malloc.)
-+
-+ You can similarly create thread-local allocators by storing
-+ mspaces as thread-locals. For example:
-+ static __thread mspace tlms = 0;
-+ void* tlmalloc(size_t bytes) {
-+ if (tlms == 0) tlms = create_mspace(0, 0);
-+ return mspace_malloc(tlms, bytes);
-+ }
-+ void tlfree(void* mem) { mspace_free(tlms, mem); }
-+
-+ Unless FOOTERS is defined, each mspace is completely independent.
-+ You cannot allocate from one and free to another (although
-+ conformance is only weakly checked, so usage errors are not always
-+ caught). If FOOTERS is defined, then each chunk carries around a tag
-+ indicating its originating mspace, and frees are directed to their
-+ originating spaces.
-+
-+ ------------------------- Compile-time options ---------------------------
-+
-+Be careful in setting #define values for numerical constants of type
-+size_t. On some systems, literal values are not automatically extended
-+to size_t precision unless they are explicitly casted.
-+
-+WIN32 default: defined if _WIN32 defined
-+ Defining WIN32 sets up defaults for MS environment and compilers.
-+ Otherwise defaults are for unix.
-+
-+MALLOC_ALIGNMENT default: (size_t)8
-+ Controls the minimum alignment for malloc'ed chunks. It must be a
-+ power of two and at least 8, even on machines for which smaller
-+ alignments would suffice. It may be defined as larger than this
-+ though. Note however that code and data structures are optimized for
-+ the case of 8-byte alignment.
-+
-+MSPACES default: 0 (false)
-+ If true, compile in support for independent allocation spaces.
-+ This is only supported if HAVE_MMAP is true.
-+
-+ONLY_MSPACES default: 0 (false)
-+ If true, only compile in mspace versions, not regular versions.
-+
-+USE_LOCKS default: 0 (false)
-+ Causes each call to each public routine to be surrounded with
-+ pthread or WIN32 mutex lock/unlock. (If set true, this can be
-+ overridden on a per-mspace basis for mspace versions.)
-+
-+FOOTERS default: 0
-+ If true, provide extra checking and dispatching by placing
-+ information in the footers of allocated chunks. This adds
-+ space and time overhead.
-+
-+INSECURE default: 0
-+ If true, omit checks for usage errors and heap space overwrites.
-+
-+USE_DL_PREFIX default: NOT defined
-+ Causes compiler to prefix all public routines with the string 'dl'.
-+ This can be useful when you only want to use this malloc in one part
-+ of a program, using your regular system malloc elsewhere.
-+
-+ABORT default: defined as abort()
-+ Defines how to abort on failed checks. On most systems, a failed
-+ check cannot die with an "assert" or even print an informative
-+ message, because the underlying print routines in turn call malloc,
-+ which will fail again. Generally, the best policy is to simply call
-+ abort(). It's not very useful to do more than this because many
-+ errors due to overwriting will show up as address faults (null, odd
-+ addresses etc) rather than malloc-triggered checks, so will also
-+ abort. Also, most compilers know that abort() does not return, so
-+ can better optimize code conditionally calling it.
-+
-+PROCEED_ON_ERROR default: defined as 0 (false)
-+ Controls whether detected bad addresses cause them to bypassed
-+ rather than aborting. If set, detected bad arguments to free and
-+ realloc are ignored. And all bookkeeping information is zeroed out
-+ upon a detected overwrite of freed heap space, thus losing the
-+ ability to ever return it from malloc again, but enabling the
-+ application to proceed. If PROCEED_ON_ERROR is defined, the
-+ static variable malloc_corruption_error_count is compiled in
-+ and can be examined to see if errors have occurred. This option
-+ generates slower code than the default abort policy.
-+
-+DEBUG default: NOT defined
-+ The DEBUG setting is mainly intended for people trying to modify
-+ this code or diagnose problems when porting to new platforms.
-+ However, it may also be able to better isolate user errors than just
-+ using runtime checks. The assertions in the check routines spell
-+ out in more detail the assumptions and invariants underlying the
-+ algorithms. The checking is fairly extensive, and will slow down
-+ execution noticeably. Calling malloc_stats or mallinfo with DEBUG
-+ set will attempt to check every non-mmapped allocated and free chunk
-+ in the course of computing the summaries.
-+
-+ABORT_ON_ASSERT_FAILURE default: defined as 1 (true)
-+ Debugging assertion failures can be nearly impossible if your
-+ version of the assert macro causes malloc to be called, which will
-+ lead to a cascade of further failures, blowing the runtime stack.
-+ ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(),
-+ which will usually make debugging easier.
-+
-+MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32
-+ The action to take before "return 0" when malloc fails to be able to
-+ return memory because there is none available.
-+
-+HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES
-+ True if this system supports sbrk or an emulation of it.
-+
-+MORECORE default: sbrk
-+ The name of the sbrk-style system routine to call to obtain more
-+ memory. See below for guidance on writing custom MORECORE
-+ functions. The type of the argument to sbrk/MORECORE varies across
-+ systems. It cannot be size_t, because it supports negative
-+ arguments, so it is normally the signed type of the same width as
-+ size_t (sometimes declared as "intptr_t"). It doesn't much matter
-+ though. Internally, we only call it with arguments less than half
-+ the max value of a size_t, which should work across all reasonable
-+ possibilities, although sometimes generating compiler warnings. See
-+ near the end of this file for guidelines for creating a custom
-+ version of MORECORE.
-+
-+MORECORE_CONTIGUOUS default: 1 (true)
-+ If true, take advantage of fact that consecutive calls to MORECORE
-+ with positive arguments always return contiguous increasing
-+ addresses. This is true of unix sbrk. It does not hurt too much to
-+ set it true anyway, since malloc copes with non-contiguities.
-+ Setting it false when definitely non-contiguous saves time
-+ and possibly wasted space it would take to discover this though.
-+
-+MORECORE_CANNOT_TRIM default: NOT defined
-+ True if MORECORE cannot release space back to the system when given
-+ negative arguments. This is generally necessary only if you are
-+ using a hand-crafted MORECORE function that cannot handle negative
-+ arguments.
-+
-+HAVE_MMAP default: 1 (true)
-+ True if this system supports mmap or an emulation of it. If so, and
-+ HAVE_MORECORE is not true, MMAP is used for all system
-+ allocation. If set and HAVE_MORECORE is true as well, MMAP is
-+ primarily used to directly allocate very large blocks. It is also
-+ used as a backup strategy in cases where MORECORE fails to provide
-+ space from system. Note: A single call to MUNMAP is assumed to be
-+ able to unmap memory that may have be allocated using multiple calls
-+ to MMAP, so long as they are adjacent.
-+
-+HAVE_MREMAP default: 1 on linux, else 0
-+ If true realloc() uses mremap() to re-allocate large blocks and
-+ extend or shrink allocation spaces.
-+
-+MMAP_CLEARS default: 1 on unix
-+ True if mmap clears memory so calloc doesn't need to. This is true
-+ for standard unix mmap using /dev/zero.
-+
-+USE_BUILTIN_FFS default: 0 (i.e., not used)
-+ Causes malloc to use the builtin ffs() function to compute indices.
-+ Some compilers may recognize and intrinsify ffs to be faster than the
-+ supplied C version. Also, the case of x86 using gcc is special-cased
-+ to an asm instruction, so is already as fast as it can be, and so
-+ this setting has no effect. (On most x86s, the asm version is only
-+ slightly faster than the C version.)
-+
-+malloc_getpagesize default: derive from system includes, or 4096.
-+ The system page size. To the extent possible, this malloc manages
-+ memory from the system in page-size units. This may be (and
-+ usually is) a function rather than a constant. This is ignored
-+ if WIN32, where page size is determined using getSystemInfo during
-+ initialization.
-+
-+USE_DEV_RANDOM default: 0 (i.e., not used)
-+ Causes malloc to use /dev/random to initialize secure magic seed for
-+ stamping footers. Otherwise, the current time is used.
-+
-+NO_MALLINFO default: 0
-+ If defined, don't compile "mallinfo". This can be a simple way
-+ of dealing with mismatches between system declarations and
-+ those in this file.
-+
-+MALLINFO_FIELD_TYPE default: size_t
-+ The type of the fields in the mallinfo struct. This was originally
-+ defined as "int" in SVID etc, but is more usefully defined as
-+ size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set
-+
-+REALLOC_ZERO_BYTES_FREES default: not defined
-+ This should be set if a call to realloc with zero bytes should
-+ be the same as a call to free. Some people think it should. Otherwise,
-+ since this malloc returns a unique pointer for malloc(0), so does
-+ realloc(p, 0).
-+
-+LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H
-+LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H
-+LACKS_STDLIB_H default: NOT defined unless on WIN32
-+ Define these if your system does not have these header files.
-+ You might need to manually insert some of the declarations they provide.
-+
-+DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS,
-+ system_info.dwAllocationGranularity in WIN32,
-+ otherwise 64K.
-+ Also settable using mallopt(M_GRANULARITY, x)
-+ The unit for allocating and deallocating memory from the system. On
-+ most systems with contiguous MORECORE, there is no reason to
-+ make this more than a page. However, systems with MMAP tend to
-+ either require or encourage larger granularities. You can increase
-+ this value to prevent system allocation functions to be called so
-+ often, especially if they are slow. The value must be at least one
-+ page and must be a power of two. Setting to 0 causes initialization
-+ to either page size or win32 region size. (Note: In previous
-+ versions of malloc, the equivalent of this option was called
-+ "TOP_PAD")
-+
-+DEFAULT_TRIM_THRESHOLD default: 2MB
-+ Also settable using mallopt(M_TRIM_THRESHOLD, x)
-+ The maximum amount of unused top-most memory to keep before
-+ releasing via malloc_trim in free(). Automatic trimming is mainly
-+ useful in long-lived programs using contiguous MORECORE. Because
-+ trimming via sbrk can be slow on some systems, and can sometimes be
-+ wasteful (in cases where programs immediately afterward allocate
-+ more large chunks) the value should be high enough so that your
-+ overall system performance would improve by releasing this much
-+ memory. As a rough guide, you might set to a value close to the
-+ average size of a process (program) running on your system.
-+ Releasing this much memory would allow such a process to run in
-+ memory. Generally, it is worth tuning trim thresholds when a
-+ program undergoes phases where several large chunks are allocated
-+ and released in ways that can reuse each other's storage, perhaps
-+ mixed with phases where there are no such chunks at all. The trim
-+ value must be greater than page size to have any useful effect. To
-+ disable trimming completely, you can set to MAX_SIZE_T. Note that the trick
-+ some people use of mallocing a huge space and then freeing it at
-+ program startup, in an attempt to reserve system memory, doesn't
-+ have the intended effect under automatic trimming, since that memory
-+ will immediately be returned to the system.
-+
-+DEFAULT_MMAP_THRESHOLD default: 256K
-+ Also settable using mallopt(M_MMAP_THRESHOLD, x)
-+ The request size threshold for using MMAP to directly service a
-+ request. Requests of at least this size that cannot be allocated
-+ using already-existing space will be serviced via mmap. (If enough
-+ normal freed space already exists it is used instead.) Using mmap
-+ segregates relatively large chunks of memory so that they can be
-+ individually obtained and released from the host system. A request
-+ serviced through mmap is never reused by any other request (at least
-+ not directly; the system may just so happen to remap successive
-+ requests to the same locations). Segregating space in this way has
-+ the benefits that: Mmapped space can always be individually released
-+ back to the system, which helps keep the system level memory demands
-+ of a long-lived program low. Also, mapped memory doesn't become
-+ `locked' between other chunks, as can happen with normally allocated
-+ chunks, which means that even trimming via malloc_trim would not
-+ release them. However, it has the disadvantage that the space
-+ cannot be reclaimed, consolidated, and then used to service later
-+ requests, as happens with normal chunks. The advantages of mmap
-+ nearly always outweigh disadvantages for "large" chunks, but the
-+ value of "large" may vary across systems. The default is an
-+ empirically derived value that works well in most systems. You can
-+ disable mmap by setting to MAX_SIZE_T.
-+
-+*/
-+
-+#ifndef WIN32
-+#ifdef _WIN32
-+#define WIN32 1
-+#endif /* _WIN32 */
-+#endif /* WIN32 */
-+#ifdef WIN32
-+#define WIN32_LEAN_AND_MEAN
-+#include
-+#define HAVE_MMAP 1
-+#define HAVE_MORECORE 0
-+#define LACKS_UNISTD_H
-+#define LACKS_SYS_PARAM_H
-+#define LACKS_SYS_MMAN_H
-+#define LACKS_STRING_H
-+#define LACKS_STRINGS_H
-+#define LACKS_SYS_TYPES_H
-+#define LACKS_ERRNO_H
-+#define MALLOC_FAILURE_ACTION
-+#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */
-+#endif /* WIN32 */
-+
-+#ifdef __OS2__
-+#define INCL_DOS
-+#include
-+#define HAVE_MMAP 1
-+#define HAVE_MORECORE 0
-+#define LACKS_SYS_MMAN_H
-+#endif /* __OS2__ */
-+
-+#if defined(DARWIN) || defined(_DARWIN)
-+/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */
-+#ifndef HAVE_MORECORE
-+#define HAVE_MORECORE 0
-+#define HAVE_MMAP 1
-+#endif /* HAVE_MORECORE */
-+#endif /* DARWIN */
-+
-+#ifndef LACKS_SYS_TYPES_H
-+#include /* For size_t */
-+#endif /* LACKS_SYS_TYPES_H */
-+
-+/* The maximum possible size_t value has all bits set */
-+#define MAX_SIZE_T (~(size_t)0)
-+
-+#ifndef ONLY_MSPACES
-+#define ONLY_MSPACES 0
-+#endif /* ONLY_MSPACES */
-+#ifndef MSPACES
-+#if ONLY_MSPACES
-+#define MSPACES 1
-+#else /* ONLY_MSPACES */
-+#define MSPACES 0
-+#endif /* ONLY_MSPACES */
-+#endif /* MSPACES */
-+#ifndef MALLOC_ALIGNMENT
-+#define MALLOC_ALIGNMENT ((size_t)8U)
-+#endif /* MALLOC_ALIGNMENT */
-+#ifndef FOOTERS
-+#define FOOTERS 0
-+#endif /* FOOTERS */
-+#ifndef ABORT
-+#define ABORT abort()
-+#endif /* ABORT */
-+#ifndef ABORT_ON_ASSERT_FAILURE
-+#define ABORT_ON_ASSERT_FAILURE 1
-+#endif /* ABORT_ON_ASSERT_FAILURE */
-+#ifndef PROCEED_ON_ERROR
-+#define PROCEED_ON_ERROR 0
-+#endif /* PROCEED_ON_ERROR */
-+#ifndef USE_LOCKS
-+#define USE_LOCKS 0
-+#endif /* USE_LOCKS */
-+#ifndef INSECURE
-+#define INSECURE 0
-+#endif /* INSECURE */
-+#ifndef HAVE_MMAP
-+#define HAVE_MMAP 1
-+#endif /* HAVE_MMAP */
-+#ifndef MMAP_CLEARS
-+#define MMAP_CLEARS 1
-+#endif /* MMAP_CLEARS */
-+#ifndef HAVE_MREMAP
-+#ifdef linux
-+#define HAVE_MREMAP 1
-+#else /* linux */
-+#define HAVE_MREMAP 0
-+#endif /* linux */
-+#endif /* HAVE_MREMAP */
-+#ifndef MALLOC_FAILURE_ACTION
-+#define MALLOC_FAILURE_ACTION errno = ENOMEM;
-+#endif /* MALLOC_FAILURE_ACTION */
-+#ifndef HAVE_MORECORE
-+#if ONLY_MSPACES
-+#define HAVE_MORECORE 0
-+#else /* ONLY_MSPACES */
-+#define HAVE_MORECORE 1
-+#endif /* ONLY_MSPACES */
-+#endif /* HAVE_MORECORE */
-+#if !HAVE_MORECORE
-+#define MORECORE_CONTIGUOUS 0
-+#else /* !HAVE_MORECORE */
-+#ifndef MORECORE
-+#define MORECORE sbrk
-+#endif /* MORECORE */
-+#ifndef MORECORE_CONTIGUOUS
-+#define MORECORE_CONTIGUOUS 1
-+#endif /* MORECORE_CONTIGUOUS */
-+#endif /* HAVE_MORECORE */
-+#ifndef DEFAULT_GRANULARITY
-+#if MORECORE_CONTIGUOUS
-+#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */
-+#else /* MORECORE_CONTIGUOUS */
-+#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
-+#endif /* MORECORE_CONTIGUOUS */
-+#endif /* DEFAULT_GRANULARITY */
-+#ifndef DEFAULT_TRIM_THRESHOLD
-+#ifndef MORECORE_CANNOT_TRIM
-+#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
-+#else /* MORECORE_CANNOT_TRIM */
-+#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T
-+#endif /* MORECORE_CANNOT_TRIM */
-+#endif /* DEFAULT_TRIM_THRESHOLD */
-+#ifndef DEFAULT_MMAP_THRESHOLD
-+#if HAVE_MMAP
-+#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U)
-+#else /* HAVE_MMAP */
-+#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
-+#endif /* HAVE_MMAP */
-+#endif /* DEFAULT_MMAP_THRESHOLD */
-+#ifndef USE_BUILTIN_FFS
-+#define USE_BUILTIN_FFS 0
-+#endif /* USE_BUILTIN_FFS */
-+#ifndef USE_DEV_RANDOM
-+#define USE_DEV_RANDOM 0
-+#endif /* USE_DEV_RANDOM */
-+#ifndef NO_MALLINFO
-+#define NO_MALLINFO 0
-+#endif /* NO_MALLINFO */
-+#ifndef MALLINFO_FIELD_TYPE
-+#define MALLINFO_FIELD_TYPE size_t
-+#endif /* MALLINFO_FIELD_TYPE */
-+
-+/*
-+ mallopt tuning options. SVID/XPG defines four standard parameter
-+ numbers for mallopt, normally defined in malloc.h. None of these
-+ are used in this malloc, so setting them has no effect. But this
-+ malloc does support the following options.
-+*/
-+
-+#define M_TRIM_THRESHOLD (-1)
-+#define M_GRANULARITY (-2)
-+#define M_MMAP_THRESHOLD (-3)
-+
-+/* ------------------------ Mallinfo declarations ------------------------ */
-+
-+#if !NO_MALLINFO
-+/*
-+ This version of malloc supports the standard SVID/XPG mallinfo
-+ routine that returns a struct containing usage properties and
-+ statistics. It should work on any system that has a
-+ /usr/include/malloc.h defining struct mallinfo. The main
-+ declaration needed is the mallinfo struct that is returned (by-copy)
-+ by mallinfo(). The malloinfo struct contains a bunch of fields that
-+ are not even meaningful in this version of malloc. These fields are
-+ are instead filled by mallinfo() with other numbers that might be of
-+ interest.
-+
-+ HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
-+ /usr/include/malloc.h file that includes a declaration of struct
-+ mallinfo. If so, it is included; else a compliant version is
-+ declared below. These must be precisely the same for mallinfo() to
-+ work. The original SVID version of this struct, defined on most
-+ systems with mallinfo, declares all fields as ints. But some others
-+ define as unsigned long. If your system defines the fields using a
-+ type of different width than listed here, you MUST #include your
-+ system version and #define HAVE_USR_INCLUDE_MALLOC_H.
-+*/
-+
-+/* #define HAVE_USR_INCLUDE_MALLOC_H */
-+
-+#ifdef HAVE_USR_INCLUDE_MALLOC_H
-+#include "/usr/include/malloc.h"
-+#else /* HAVE_USR_INCLUDE_MALLOC_H */
-+
-+/* HP-UX's stdlib.h redefines mallinfo unless _STRUCT_MALLINFO is defined */
-+#define _STRUCT_MALLINFO
-+
-+struct mallinfo {
-+ MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
-+ MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
-+ MALLINFO_FIELD_TYPE smblks; /* always 0 */
-+ MALLINFO_FIELD_TYPE hblks; /* always 0 */
-+ MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */
-+ MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */
-+ MALLINFO_FIELD_TYPE fsmblks; /* always 0 */
-+ MALLINFO_FIELD_TYPE uordblks; /* total allocated space */
-+ MALLINFO_FIELD_TYPE fordblks; /* total free space */
-+ MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */
-+};
-+
-+#endif /* HAVE_USR_INCLUDE_MALLOC_H */
-+#endif /* NO_MALLINFO */
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif /* __cplusplus */
-+
-+#if !ONLY_MSPACES
-+
-+/* ------------------- Declarations of public routines ------------------- */
-+
-+#ifndef USE_DL_PREFIX
-+#define dlcalloc calloc
-+#define dlfree free
-+#define dlmalloc malloc
-+#define dlmemalign memalign
-+#define dlrealloc realloc
-+#define dlvalloc valloc
-+#define dlpvalloc pvalloc
-+#define dlmallinfo mallinfo
-+#define dlmallopt mallopt
-+#define dlmalloc_trim malloc_trim
-+#define dlmalloc_stats malloc_stats
-+#define dlmalloc_usable_size malloc_usable_size
-+#define dlmalloc_footprint malloc_footprint
-+#define dlmalloc_max_footprint malloc_max_footprint
-+#define dlindependent_calloc independent_calloc
-+#define dlindependent_comalloc independent_comalloc
-+#endif /* USE_DL_PREFIX */
-+
-+
-+/*
-+ malloc(size_t n)
-+ Returns a pointer to a newly allocated chunk of at least n bytes, or
-+ null if no space is available, in which case errno is set to ENOMEM
-+ on ANSI C systems.
-+
-+ If n is zero, malloc returns a minimum-sized chunk. (The minimum
-+ size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
-+ systems.) Note that size_t is an unsigned type, so calls with
-+ arguments that would be negative if signed are interpreted as
-+ requests for huge amounts of space, which will often fail. The
-+ maximum supported value of n differs across systems, but is in all
-+ cases less than the maximum representable value of a size_t.
-+*/
-+void* dlmalloc(size_t);
-+
-+/*
-+ free(void* p)
-+ Releases the chunk of memory pointed to by p, that had been previously
-+ allocated using malloc or a related routine such as realloc.
-+ It has no effect if p is null. If p was not malloced or already
-+ freed, free(p) will by default cause the current program to abort.
-+*/
-+void dlfree(void*);
-+
-+/*
-+ calloc(size_t n_elements, size_t element_size);
-+ Returns a pointer to n_elements * element_size bytes, with all locations
-+ set to zero.
-+*/
-+void* dlcalloc(size_t, size_t);
-+
-+/*
-+ realloc(void* p, size_t n)
-+ Returns a pointer to a chunk of size n that contains the same data
-+ as does chunk p up to the minimum of (n, p's size) bytes, or null
-+ if no space is available.
-+
-+ The returned pointer may or may not be the same as p. The algorithm
-+ prefers extending p in most cases when possible, otherwise it
-+ employs the equivalent of a malloc-copy-free sequence.
-+
-+ If p is null, realloc is equivalent to malloc.
-+
-+ If space is not available, realloc returns null, errno is set (if on
-+ ANSI) and p is NOT freed.
-+
-+ if n is for fewer bytes than already held by p, the newly unused
-+ space is lopped off and freed if possible. realloc with a size
-+ argument of zero (re)allocates a minimum-sized chunk.
-+
-+ The old unix realloc convention of allowing the last-free'd chunk
-+ to be used as an argument to realloc is not supported.
-+*/
-+
-+void* dlrealloc(void*, size_t);
-+
-+/*
-+ memalign(size_t alignment, size_t n);
-+ Returns a pointer to a newly allocated chunk of n bytes, aligned
-+ in accord with the alignment argument.
-+
-+ The alignment argument should be a power of two. If the argument is
-+ not a power of two, the nearest greater power is used.
-+ 8-byte alignment is guaranteed by normal malloc calls, so don't
-+ bother calling memalign with an argument of 8 or less.
-+
-+ Overreliance on memalign is a sure way to fragment space.
-+*/
-+void* dlmemalign(size_t, size_t);
-+
-+/*
-+ valloc(size_t n);
-+ Equivalent to memalign(pagesize, n), where pagesize is the page
-+ size of the system. If the pagesize is unknown, 4096 is used.
-+*/
-+void* dlvalloc(size_t);
-+
-+/*
-+ mallopt(int parameter_number, int parameter_value)
-+ Sets tunable parameters The format is to provide a
-+ (parameter-number, parameter-value) pair. mallopt then sets the
-+ corresponding parameter to the argument value if it can (i.e., so
-+ long as the value is meaningful), and returns 1 if successful else
-+ 0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
-+ normally defined in malloc.h. None of these are use in this malloc,
-+ so setting them has no effect. But this malloc also supports other
-+ options in mallopt. See below for details. Briefly, supported
-+ parameters are as follows (listed defaults are for "typical"
-+ configurations).
-+
-+ Symbol param # default allowed param values
-+ M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables)
-+ M_GRANULARITY -2 page size any power of 2 >= page size
-+ M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
-+*/
-+int dlmallopt(int, int);
-+
-+/*
-+ malloc_footprint();
-+ Returns the number of bytes obtained from the system. The total
-+ number of bytes allocated by malloc, realloc etc., is less than this
-+ value. Unlike mallinfo, this function returns only a precomputed
-+ result, so can be called frequently to monitor memory consumption.
-+ Even if locks are otherwise defined, this function does not use them,
-+ so results might not be up to date.
-+*/
-+size_t dlmalloc_footprint(void);
-+
-+/*
-+ malloc_max_footprint();
-+ Returns the maximum number of bytes obtained from the system. This
-+ value will be greater than current footprint if deallocated space
-+ has been reclaimed by the system. The peak number of bytes allocated
-+ by malloc, realloc etc., is less than this value. Unlike mallinfo,
-+ this function returns only a precomputed result, so can be called
-+ frequently to monitor memory consumption. Even if locks are
-+ otherwise defined, this function does not use them, so results might
-+ not be up to date.
-+*/
-+size_t dlmalloc_max_footprint(void);
-+
-+#if !NO_MALLINFO
-+/*
-+ mallinfo()
-+ Returns (by copy) a struct containing various summary statistics:
-+
-+ arena: current total non-mmapped bytes allocated from system
-+ ordblks: the number of free chunks
-+ smblks: always zero.
-+ hblks: current number of mmapped regions
-+ hblkhd: total bytes held in mmapped regions
-+ usmblks: the maximum total allocated space. This will be greater
-+ than current total if trimming has occurred.
-+ fsmblks: always zero
-+ uordblks: current total allocated space (normal or mmapped)
-+ fordblks: total free space
-+ keepcost: the maximum number of bytes that could ideally be released
-+ back to system via malloc_trim. ("ideally" means that
-+ it ignores page restrictions etc.)
-+
-+ Because these fields are ints, but internal bookkeeping may
-+ be kept as longs, the reported values may wrap around zero and
-+ thus be inaccurate.
-+*/
-+struct mallinfo dlmallinfo(void);
-+#endif /* NO_MALLINFO */
-+
-+/*
-+ independent_calloc(size_t n_elements, size_t element_size, void* chunks[]);
-+
-+ independent_calloc is similar to calloc, but instead of returning a
-+ single cleared space, it returns an array of pointers to n_elements
-+ independent elements that can hold contents of size elem_size, each
-+ of which starts out cleared, and can be independently freed,
-+ realloc'ed etc. The elements are guaranteed to be adjacently
-+ allocated (this is not guaranteed to occur with multiple callocs or
-+ mallocs), which may also improve cache locality in some
-+ applications.
-+
-+ The "chunks" argument is optional (i.e., may be null, which is
-+ probably the most typical usage). If it is null, the returned array
-+ is itself dynamically allocated and should also be freed when it is
-+ no longer needed. Otherwise, the chunks array must be of at least
-+ n_elements in length. It is filled in with the pointers to the
-+ chunks.
-+
-+ In either case, independent_calloc returns this pointer array, or
-+ null if the allocation failed. If n_elements is zero and "chunks"
-+ is null, it returns a chunk representing an array with zero elements
-+ (which should be freed if not wanted).
-+
-+ Each element must be individually freed when it is no longer
-+ needed. If you'd like to instead be able to free all at once, you
-+ should instead use regular calloc and assign pointers into this
-+ space to represent elements. (In this case though, you cannot
-+ independently free elements.)
-+
-+ independent_calloc simplifies and speeds up implementations of many
-+ kinds of pools. It may also be useful when constructing large data
-+ structures that initially have a fixed number of fixed-sized nodes,
-+ but the number is not known at compile time, and some of the nodes
-+ may later need to be freed. For example:
-+
-+ struct Node { int item; struct Node* next; };
-+
-+ struct Node* build_list() {
-+ struct Node** pool;
-+ int n = read_number_of_nodes_needed();
-+ if (n <= 0) return 0;
-+ pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
-+ if (pool == 0) die();
-+ // organize into a linked list...
-+ struct Node* first = pool[0];
-+ for (i = 0; i < n-1; ++i)
-+ pool[i]->next = pool[i+1];
-+ free(pool); // Can now free the array (or not, if it is needed later)
-+ return first;
-+ }
-+*/
-+void** dlindependent_calloc(size_t, size_t, void**);
-+
-+/*
-+ independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
-+
-+ independent_comalloc allocates, all at once, a set of n_elements
-+ chunks with sizes indicated in the "sizes" array. It returns
-+ an array of pointers to these elements, each of which can be
-+ independently freed, realloc'ed etc. The elements are guaranteed to
-+ be adjacently allocated (this is not guaranteed to occur with
-+ multiple callocs or mallocs), which may also improve cache locality
-+ in some applications.
-+
-+ The "chunks" argument is optional (i.e., may be null). If it is null
-+ the returned array is itself dynamically allocated and should also
-+ be freed when it is no longer needed. Otherwise, the chunks array
-+ must be of at least n_elements in length. It is filled in with the
-+ pointers to the chunks.
-+
-+ In either case, independent_comalloc returns this pointer array, or
-+ null if the allocation failed. If n_elements is zero and chunks is
-+ null, it returns a chunk representing an array with zero elements
-+ (which should be freed if not wanted).
-+
-+ Each element must be individually freed when it is no longer
-+ needed. If you'd like to instead be able to free all at once, you
-+ should instead use a single regular malloc, and assign pointers at
-+ particular offsets in the aggregate space. (In this case though, you
-+ cannot independently free elements.)
-+
-+ independent_comallac differs from independent_calloc in that each
-+ element may have a different size, and also that it does not
-+ automatically clear elements.
-+
-+ independent_comalloc can be used to speed up allocation in cases
-+ where several structs or objects must always be allocated at the
-+ same time. For example:
-+
-+ struct Head { ... }
-+ struct Foot { ... }
-+
-+ void send_message(char* msg) {
-+ int msglen = strlen(msg);
-+ size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
-+ void* chunks[3];
-+ if (independent_comalloc(3, sizes, chunks) == 0)
-+ die();
-+ struct Head* head = (struct Head*)(chunks[0]);
-+ char* body = (char*)(chunks[1]);
-+ struct Foot* foot = (struct Foot*)(chunks[2]);
-+ // ...
-+ }
-+
-+ In general though, independent_comalloc is worth using only for
-+ larger values of n_elements. For small values, you probably won't
-+ detect enough difference from series of malloc calls to bother.
-+
-+ Overuse of independent_comalloc can increase overall memory usage,
-+ since it cannot reuse existing noncontiguous small chunks that
-+ might be available for some of the elements.
-+*/
-+void** dlindependent_comalloc(size_t, size_t*, void**);
-+
-+
-+/*
-+ pvalloc(size_t n);
-+ Equivalent to valloc(minimum-page-that-holds(n)), that is,
-+ round up n to nearest pagesize.
-+ */
-+void* dlpvalloc(size_t);
-+
-+/*
-+ malloc_trim(size_t pad);
-+
-+ If possible, gives memory back to the system (via negative arguments
-+ to sbrk) if there is unused memory at the `high' end of the malloc
-+ pool or in unused MMAP segments. You can call this after freeing
-+ large blocks of memory to potentially reduce the system-level memory
-+ requirements of a program. However, it cannot guarantee to reduce
-+ memory. Under some allocation patterns, some large free blocks of
-+ memory will be locked between two used chunks, so they cannot be
-+ given back to the system.
-+
-+ The `pad' argument to malloc_trim represents the amount of free
-+ trailing space to leave untrimmed. If this argument is zero, only
-+ the minimum amount of memory to maintain internal data structures
-+ will be left. Non-zero arguments can be supplied to maintain enough
-+ trailing space to service future expected allocations without having
-+ to re-obtain memory from the system.
-+
-+ Malloc_trim returns 1 if it actually released any memory, else 0.
-+*/
-+int dlmalloc_trim(size_t);
-+
-+/*
-+ malloc_usable_size(void* p);
-+
-+ Returns the number of bytes you can actually use in
-+ an allocated chunk, which may be more than you requested (although
-+ often not) due to alignment and minimum size constraints.
-+ You can use this many bytes without worrying about
-+ overwriting other allocated objects. This is not a particularly great
-+ programming practice. malloc_usable_size can be more useful in
-+ debugging and assertions, for example:
-+
-+ p = malloc(n);
-+ assert(malloc_usable_size(p) >= 256);
-+*/
-+size_t dlmalloc_usable_size(void*);
-+
-+/*
-+ malloc_stats();
-+ Prints on stderr the amount of space obtained from the system (both
-+ via sbrk and mmap), the maximum amount (which may be more than
-+ current if malloc_trim and/or munmap got called), and the current
-+ number of bytes allocated via malloc (or realloc, etc) but not yet
-+ freed. Note that this is the number of bytes allocated, not the
-+ number requested. It will be larger than the number requested
-+ because of alignment and bookkeeping overhead. Because it includes
-+ alignment wastage as being in use, this figure may be greater than
-+ zero even when no user-level chunks are allocated.
-+
-+ The reported current and maximum system memory can be inaccurate if
-+ a program makes other calls to system memory allocation functions
-+ (normally sbrk) outside of malloc.
-+
-+ malloc_stats prints only the most commonly interesting statistics.
-+ More information can be obtained by calling mallinfo.
-+*/
-+void dlmalloc_stats(void);
-+
-+#endif /* ONLY_MSPACES */
-+
-+#if MSPACES
-+
-+/*
-+ mspace is an opaque type representing an independent
-+ region of space that supports mspace_malloc, etc.
-+*/
-+typedef void* mspace;
-+
-+/*
-+ create_mspace creates and returns a new independent space with the
-+ given initial capacity, or, if 0, the default granularity size. It
-+ returns null if there is no system memory available to create the
-+ space. If argument locked is non-zero, the space uses a separate
-+ lock to control access. The capacity of the space will grow
-+ dynamically as needed to service mspace_malloc requests. You can
-+ control the sizes of incremental increases of this space by
-+ compiling with a different DEFAULT_GRANULARITY or dynamically
-+ setting with mallopt(M_GRANULARITY, value).
-+*/
-+mspace create_mspace(size_t capacity, int locked);
-+
-+/*
-+ destroy_mspace destroys the given space, and attempts to return all
-+ of its memory back to the system, returning the total number of
-+ bytes freed. After destruction, the results of access to all memory
-+ used by the space become undefined.
-+*/
-+size_t destroy_mspace(mspace msp);
-+
-+/*
-+ create_mspace_with_base uses the memory supplied as the initial base
-+ of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
-+ space is used for bookkeeping, so the capacity must be at least this
-+ large. (Otherwise 0 is returned.) When this initial space is
-+ exhausted, additional memory will be obtained from the system.
-+ Destroying this space will deallocate all additionally allocated
-+ space (if possible) but not the initial base.
-+*/
-+mspace create_mspace_with_base(void* base, size_t capacity, int locked);
-+
-+/*
-+ mspace_malloc behaves as malloc, but operates within
-+ the given space.
-+*/
-+void* mspace_malloc(mspace msp, size_t bytes);
-+
-+/*
-+ mspace_free behaves as free, but operates within
-+ the given space.
-+
-+ If compiled with FOOTERS==1, mspace_free is not actually needed.
-+ free may be called instead of mspace_free because freed chunks from
-+ any space are handled by their originating spaces.
-+*/
-+void mspace_free(mspace msp, void* mem);
-+
-+/*
-+ mspace_realloc behaves as realloc, but operates within
-+ the given space.
-+
-+ If compiled with FOOTERS==1, mspace_realloc is not actually
-+ needed. realloc may be called instead of mspace_realloc because
-+ realloced chunks from any space are handled by their originating
-+ spaces.
-+*/
-+void* mspace_realloc(mspace msp, void* mem, size_t newsize);
-+
-+/*
-+ mspace_calloc behaves as calloc, but operates within
-+ the given space.
-+*/
-+void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
-+
-+/*
-+ mspace_memalign behaves as memalign, but operates within
-+ the given space.
-+*/
-+void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
-+
-+/*
-+ mspace_independent_calloc behaves as independent_calloc, but
-+ operates within the given space.
-+*/
-+void** mspace_independent_calloc(mspace msp, size_t n_elements,
-+ size_t elem_size, void* chunks[]);
-+
-+/*
-+ mspace_independent_comalloc behaves as independent_comalloc, but
-+ operates within the given space.
-+*/
-+void** mspace_independent_comalloc(mspace msp, size_t n_elements,
-+ size_t sizes[], void* chunks[]);
-+
-+/*
-+ mspace_footprint() returns the number of bytes obtained from the
-+ system for this space.
-+*/
-+size_t mspace_footprint(mspace msp);
-+
-+/*
-+ mspace_max_footprint() returns the peak number of bytes obtained from the
-+ system for this space.
-+*/
-+size_t mspace_max_footprint(mspace msp);
-+
-+
-+#if !NO_MALLINFO
-+/*
-+ mspace_mallinfo behaves as mallinfo, but reports properties of
-+ the given space.
-+*/
-+struct mallinfo mspace_mallinfo(mspace msp);
-+#endif /* NO_MALLINFO */
-+
-+/*
-+ mspace_malloc_stats behaves as malloc_stats, but reports
-+ properties of the given space.
-+*/
-+void mspace_malloc_stats(mspace msp);
-+
-+/*
-+ mspace_trim behaves as malloc_trim, but
-+ operates within the given space.
-+*/
-+int mspace_trim(mspace msp, size_t pad);
-+
-+/*
-+ An alias for mallopt.
-+*/
-+int mspace_mallopt(int, int);
-+
-+#endif /* MSPACES */
-+
-+#ifdef __cplusplus
-+}; /* end of extern "C" */
-+#endif /* __cplusplus */
-+
-+/*
-+ ========================================================================
-+ To make a fully customizable malloc.h header file, cut everything
-+ above this line, put into file malloc.h, edit to suit, and #include it
-+ on the next line, as well as in programs that use this malloc.
-+ ========================================================================
-+*/
-+
-+/* #include "malloc.h" */
-+
-+/*------------------------------ internal #includes ---------------------- */
-+
-+#ifdef _MSC_VER
-+#pragma warning( disable : 4146 ) /* no "unsigned" warnings */
-+#endif /* _MSC_VER */
-+
-+#include /* for printing in malloc_stats */
-+
-+#ifndef LACKS_ERRNO_H
-+#include /* for MALLOC_FAILURE_ACTION */
-+#endif /* LACKS_ERRNO_H */
-+#if FOOTERS
-+#include /* for magic initialization */
-+#endif /* FOOTERS */
-+#ifndef LACKS_STDLIB_H
-+#include /* for abort() */
-+#endif /* LACKS_STDLIB_H */
-+#ifdef DEBUG
-+#if ABORT_ON_ASSERT_FAILURE
-+#define assert(x) if(!(x)) ABORT
-+#else /* ABORT_ON_ASSERT_FAILURE */
-+#include
-+#endif /* ABORT_ON_ASSERT_FAILURE */
-+#else /* DEBUG */
-+#define assert(x)
-+#endif /* DEBUG */
-+#ifndef LACKS_STRING_H
-+#include /* for memset etc */
-+#endif /* LACKS_STRING_H */
-+#if USE_BUILTIN_FFS
-+#ifndef LACKS_STRINGS_H
-+#include /* for ffs */
-+#endif /* LACKS_STRINGS_H */
-+#endif /* USE_BUILTIN_FFS */
-+#if HAVE_MMAP
-+#ifndef LACKS_SYS_MMAN_H
-+#include /* for mmap */
-+#endif /* LACKS_SYS_MMAN_H */
-+#ifndef LACKS_FCNTL_H
-+#include
-+#endif /* LACKS_FCNTL_H */
-+#endif /* HAVE_MMAP */
-+#if HAVE_MORECORE
-+#ifndef LACKS_UNISTD_H
-+#include /* for sbrk */
-+#else /* LACKS_UNISTD_H */
-+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
-+extern void* sbrk(ptrdiff_t);
-+#endif /* FreeBSD etc */
-+#endif /* LACKS_UNISTD_H */
-+#endif /* HAVE_MMAP */
-+
-+#ifndef WIN32
-+#ifndef malloc_getpagesize
-+# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */
-+# ifndef _SC_PAGE_SIZE
-+# define _SC_PAGE_SIZE _SC_PAGESIZE
-+# endif
-+# endif
-+# ifdef _SC_PAGE_SIZE
-+# define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
-+# else
-+# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
-+ extern size_t getpagesize();
-+# define malloc_getpagesize getpagesize()
-+# else
-+# ifdef WIN32 /* use supplied emulation of getpagesize */
-+# define malloc_getpagesize getpagesize()
-+# else
-+# ifndef LACKS_SYS_PARAM_H
-+# include
-+# endif
-+# ifdef EXEC_PAGESIZE
-+# define malloc_getpagesize EXEC_PAGESIZE
-+# else
-+# ifdef NBPG
-+# ifndef CLSIZE
-+# define malloc_getpagesize NBPG
-+# else
-+# define malloc_getpagesize (NBPG * CLSIZE)
-+# endif
-+# else
-+# ifdef NBPC
-+# define malloc_getpagesize NBPC
-+# else
-+# ifdef PAGESIZE
-+# define malloc_getpagesize PAGESIZE
-+# else /* just guess */
-+# define malloc_getpagesize ((size_t)4096U)
-+# endif
-+# endif
-+# endif
-+# endif
-+# endif
-+# endif
-+# endif
-+#endif
-+#endif
-+
-+/* ------------------- size_t and alignment properties -------------------- */
-+
-+/* The byte and bit size of a size_t */
-+#define SIZE_T_SIZE (sizeof(size_t))
-+#define SIZE_T_BITSIZE (sizeof(size_t) << 3)
-+
-+/* Some constants coerced to size_t */
-+/* Annoying but necessary to avoid errors on some platforms */
-+#define SIZE_T_ZERO ((size_t)0)
-+#define SIZE_T_ONE ((size_t)1)
-+#define SIZE_T_TWO ((size_t)2)
-+#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
-+#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
-+#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
-+#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U)
-+
-+/* The bit mask value corresponding to MALLOC_ALIGNMENT */
-+#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
-+
-+/* True if address a has acceptable alignment */
-+#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0)
-+
-+/* the number of bytes to offset an address to align it */
-+#define align_offset(A)\
-+ ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
-+ ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
-+
-+/* -------------------------- MMAP preliminaries ------------------------- */
-+
-+/*
-+ If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and
-+ checks to fail so compiler optimizer can delete code rather than
-+ using so many "#if"s.
-+*/
-+
-+
-+/* MORECORE and MMAP must return MFAIL on failure */
-+#define MFAIL ((void*)(MAX_SIZE_T))
-+#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */
-+
-+#if !HAVE_MMAP
-+#define IS_MMAPPED_BIT (SIZE_T_ZERO)
-+#define USE_MMAP_BIT (SIZE_T_ZERO)
-+#define CALL_MMAP(s) MFAIL
-+#define CALL_MUNMAP(a, s) (-1)
-+#define DIRECT_MMAP(s) MFAIL
-+
-+#else /* HAVE_MMAP */
-+#define IS_MMAPPED_BIT (SIZE_T_ONE)
-+#define USE_MMAP_BIT (SIZE_T_ONE)
-+
-+#if !defined(WIN32) && !defined (__OS2__)
-+#define CALL_MUNMAP(a, s) munmap((a), (s))
-+#define MMAP_PROT (PROT_READ|PROT_WRITE)
-+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-+#define MAP_ANONYMOUS MAP_ANON
-+#endif /* MAP_ANON */
-+#ifdef MAP_ANONYMOUS
-+#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
-+#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0)
-+#else /* MAP_ANONYMOUS */
-+/*
-+ Nearly all versions of mmap support MAP_ANONYMOUS, so the following
-+ is unlikely to be needed, but is supplied just in case.
-+*/
-+#define MMAP_FLAGS (MAP_PRIVATE)
-+static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
-+#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \
-+ (dev_zero_fd = open("/dev/zero", O_RDWR), \
-+ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \
-+ mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0))
-+#endif /* MAP_ANONYMOUS */
-+
-+#define DIRECT_MMAP(s) CALL_MMAP(s)
-+
-+#elif defined(__OS2__)
-+
-+/* OS/2 MMAP via DosAllocMem */
-+static void* os2mmap(size_t size) {
-+ void* ptr;
-+ if (DosAllocMem(&ptr, size, OBJ_ANY|PAG_COMMIT|PAG_READ|PAG_WRITE) &&
-+ DosAllocMem(&ptr, size, PAG_COMMIT|PAG_READ|PAG_WRITE))
-+ return MFAIL;
-+ return ptr;
-+}
-+
-+#define os2direct_mmap(n) os2mmap(n)
-+
-+/* This function supports releasing coalesed segments */
-+static int os2munmap(void* ptr, size_t size) {
-+ while (size) {
-+ ULONG ulSize = size;
-+ ULONG ulFlags = 0;
-+ if (DosQueryMem(ptr, &ulSize, &ulFlags) != 0)
-+ return -1;
-+ if ((ulFlags & PAG_BASE) == 0 ||(ulFlags & PAG_COMMIT) == 0 ||
-+ ulSize > size)
-+ return -1;
-+ if (DosFreeMem(ptr) != 0)
-+ return -1;
-+ ptr = ( void * ) ( ( char * ) ptr + ulSize );
-+ size -= ulSize;
-+ }
-+ return 0;
-+}
-+
-+#define CALL_MMAP(s) os2mmap(s)
-+#define CALL_MUNMAP(a, s) os2munmap((a), (s))
-+#define DIRECT_MMAP(s) os2direct_mmap(s)
-+
-+#else /* WIN32 */
-+
-+/* Win32 MMAP via VirtualAlloc */
-+static void* win32mmap(size_t size) {
-+ void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
-+ return (ptr != 0)? ptr: MFAIL;
-+}
-+
-+/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
-+static void* win32direct_mmap(size_t size) {
-+ void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
-+ PAGE_EXECUTE_READWRITE);
-+ return (ptr != 0)? ptr: MFAIL;
-+}
-+
-+/* This function supports releasing coalesed segments */
-+static int win32munmap(void* ptr, size_t size) {
-+ MEMORY_BASIC_INFORMATION minfo;
-+ char* cptr = ptr;
-+ while (size) {
-+ if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
-+ return -1;
-+ if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
-+ minfo.State != MEM_COMMIT || minfo.RegionSize > size)
-+ return -1;
-+ if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
-+ return -1;
-+ cptr += minfo.RegionSize;
-+ size -= minfo.RegionSize;
-+ }
-+ return 0;
-+}
-+
-+#define CALL_MMAP(s) win32mmap(s)
-+#define CALL_MUNMAP(a, s) win32munmap((a), (s))
-+#define DIRECT_MMAP(s) win32direct_mmap(s)
-+#endif /* WIN32 */
-+#endif /* HAVE_MMAP */
-+
-+#if HAVE_MMAP && HAVE_MREMAP
-+#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv))
-+#else /* HAVE_MMAP && HAVE_MREMAP */
-+#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL
-+#endif /* HAVE_MMAP && HAVE_MREMAP */
-+
-+#if HAVE_MORECORE
-+#define CALL_MORECORE(S) MORECORE(S)
-+#else /* HAVE_MORECORE */
-+#define CALL_MORECORE(S) MFAIL
-+#endif /* HAVE_MORECORE */
-+
-+/* mstate bit set if contiguous morecore disabled or failed */
-+#define USE_NONCONTIGUOUS_BIT (4U)
-+
-+/* segment bit set in create_mspace_with_base */
-+#define EXTERN_BIT (8U)
-+
-+
-+/* --------------------------- Lock preliminaries ------------------------ */
-+
-+#if USE_LOCKS
-+
-+/*
-+ When locks are defined, there are up to two global locks:
-+
-+ * If HAVE_MORECORE, morecore_mutex protects sequences of calls to
-+ MORECORE. In many cases sys_alloc requires two calls, that should
-+ not be interleaved with calls by other threads. This does not
-+ protect against direct calls to MORECORE by other threads not
-+ using this lock, so there is still code to cope the best we can on
-+ interference.
-+
-+ * magic_init_mutex ensures that mparams.magic and other
-+ unique mparams values are initialized only once.
-+*/
-+
-+#if !defined(WIN32) && !defined(__OS2__)
-+/* By default use posix locks */
-+#include
-+#define MLOCK_T pthread_mutex_t
-+#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL)
-+#define ACQUIRE_LOCK(l) pthread_mutex_lock(l)
-+#define RELEASE_LOCK(l) pthread_mutex_unlock(l)
-+
-+#if HAVE_MORECORE
-+static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER;
-+#endif /* HAVE_MORECORE */
-+
-+static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER;
-+
-+#elif defined(__OS2__)
-+#define MLOCK_T HMTX
-+#define INITIAL_LOCK(l) DosCreateMutexSem(0, l, 0, FALSE)
-+#define ACQUIRE_LOCK(l) DosRequestMutexSem(*l, SEM_INDEFINITE_WAIT)
-+#define RELEASE_LOCK(l) DosReleaseMutexSem(*l)
-+#if HAVE_MORECORE
-+static MLOCK_T morecore_mutex;
-+#endif /* HAVE_MORECORE */
-+static MLOCK_T magic_init_mutex;
-+
-+#else /* WIN32 */
-+/*
-+ Because lock-protected regions have bounded times, and there
-+ are no recursive lock calls, we can use simple spinlocks.
-+*/
-+
-+#define MLOCK_T long
-+static int win32_acquire_lock (MLOCK_T *sl) {
-+ for (;;) {
-+#ifdef InterlockedCompareExchangePointer
-+ if (!InterlockedCompareExchange(sl, 1, 0))
-+ return 0;
-+#else /* Use older void* version */
-+ if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0))
-+ return 0;
-+#endif /* InterlockedCompareExchangePointer */
-+ Sleep (0);
-+ }
-+}
-+
-+static void win32_release_lock (MLOCK_T *sl) {
-+ InterlockedExchange (sl, 0);
-+}
-+
-+#define INITIAL_LOCK(l) *(l)=0
-+#define ACQUIRE_LOCK(l) win32_acquire_lock(l)
-+#define RELEASE_LOCK(l) win32_release_lock(l)
-+#if HAVE_MORECORE
-+static MLOCK_T morecore_mutex;
-+#endif /* HAVE_MORECORE */
-+static MLOCK_T magic_init_mutex;
-+#endif /* WIN32 */
-+
-+#define USE_LOCK_BIT (2U)
-+#else /* USE_LOCKS */
-+#define USE_LOCK_BIT (0U)
-+#define INITIAL_LOCK(l)
-+#endif /* USE_LOCKS */
-+
-+#if USE_LOCKS && HAVE_MORECORE
-+#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex);
-+#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex);
-+#else /* USE_LOCKS && HAVE_MORECORE */
-+#define ACQUIRE_MORECORE_LOCK()
-+#define RELEASE_MORECORE_LOCK()
-+#endif /* USE_LOCKS && HAVE_MORECORE */
-+
-+#if USE_LOCKS
-+#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex);
-+#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex);
-+#else /* USE_LOCKS */
-+#define ACQUIRE_MAGIC_INIT_LOCK()
-+#define RELEASE_MAGIC_INIT_LOCK()
-+#endif /* USE_LOCKS */
-+
-+
-+/* ----------------------- Chunk representations ------------------------ */
-+
-+/*
-+ (The following includes lightly edited explanations by Colin Plumb.)
-+
-+ The malloc_chunk declaration below is misleading (but accurate and
-+ necessary). It declares a "view" into memory allowing access to
-+ necessary fields at known offsets from a given base.
-+
-+ Chunks of memory are maintained using a `boundary tag' method as
-+ originally described by Knuth. (See the paper by Paul Wilson
-+ ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such
-+ techniques.) Sizes of free chunks are stored both in the front of
-+ each chunk and at the end. This makes consolidating fragmented
-+ chunks into bigger chunks fast. The head fields also hold bits
-+ representing whether chunks are free or in use.
-+
-+ Here are some pictures to make it clearer. They are "exploded" to
-+ show that the state of a chunk can be thought of as extending from
-+ the high 31 bits of the head field of its header through the
-+ prev_foot and PINUSE_BIT bit of the following chunk header.
-+
-+ A chunk that's in use looks like:
-+
-+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Size of previous chunk (if P = 1) |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
-+ | Size of this chunk 1| +-+
-+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | |
-+ +- -+
-+ | |
-+ +- -+
-+ | :
-+ +- size - sizeof(size_t) available payload bytes -+
-+ : |
-+ chunk-> +- -+
-+ | |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|
-+ | Size of next chunk (may or may not be in use) | +-+
-+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+
-+ And if it's free, it looks like this:
-+
-+ chunk-> +- -+
-+ | User payload (must be in use, or we would have merged!) |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|
-+ | Size of this chunk 0| +-+
-+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Next pointer |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Prev pointer |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | :
-+ +- size - sizeof(struct chunk) unused bytes -+
-+ : |
-+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Size of this chunk |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|
-+ | Size of next chunk (must be in use, or we would have merged)| +-+
-+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | :
-+ +- User payload -+
-+ : |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ |0|
-+ +-+
-+ Note that since we always merge adjacent free chunks, the chunks
-+ adjacent to a free chunk must be in use.
-+
-+ Given a pointer to a chunk (which can be derived trivially from the
-+ payload pointer) we can, in O(1) time, find out whether the adjacent
-+ chunks are free, and if so, unlink them from the lists that they
-+ are on and merge them with the current chunk.
-+
-+ Chunks always begin on even word boundaries, so the mem portion
-+ (which is returned to the user) is also on an even word boundary, and
-+ thus at least double-word aligned.
-+
-+ The P (PINUSE_BIT) bit, stored in the unused low-order bit of the
-+ chunk size (which is always a multiple of two words), is an in-use
-+ bit for the *previous* chunk. If that bit is *clear*, then the
-+ word before the current chunk size contains the previous chunk
-+ size, and can be used to find the front of the previous chunk.
-+ The very first chunk allocated always has this bit set, preventing
-+ access to non-existent (or non-owned) memory. If pinuse is set for
-+ any given chunk, then you CANNOT determine the size of the
-+ previous chunk, and might even get a memory addressing fault when
-+ trying to do so.
-+
-+ The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of
-+ the chunk size redundantly records whether the current chunk is
-+ inuse. This redundancy enables usage checks within free and realloc,
-+ and reduces indirection when freeing and consolidating chunks.
-+
-+ Each freshly allocated chunk must have both cinuse and pinuse set.
-+ That is, each allocated chunk borders either a previously allocated
-+ and still in-use chunk, or the base of its memory arena. This is
-+ ensured by making all allocations from the the `lowest' part of any
-+ found chunk. Further, no free chunk physically borders another one,
-+ so each free chunk is known to be preceded and followed by either
-+ inuse chunks or the ends of memory.
-+
-+ Note that the `foot' of the current chunk is actually represented
-+ as the prev_foot of the NEXT chunk. This makes it easier to
-+ deal with alignments etc but can be very confusing when trying
-+ to extend or adapt this code.
-+
-+ The exceptions to all this are
-+
-+ 1. The special chunk `top' is the top-most available chunk (i.e.,
-+ the one bordering the end of available memory). It is treated
-+ specially. Top is never included in any bin, is used only if
-+ no other chunk is available, and is released back to the
-+ system if it is very large (see M_TRIM_THRESHOLD). In effect,
-+ the top chunk is treated as larger (and thus less well
-+ fitting) than any other available chunk. The top chunk
-+ doesn't update its trailing size field since there is no next
-+ contiguous chunk that would have to index off it. However,
-+ space is still allocated for it (TOP_FOOT_SIZE) to enable
-+ separation or merging when space is extended.
-+
-+ 3. Chunks allocated via mmap, which have the lowest-order bit
-+ (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set
-+ PINUSE_BIT in their head fields. Because they are allocated
-+ one-by-one, each must carry its own prev_foot field, which is
-+ also used to hold the offset this chunk has within its mmapped
-+ region, which is needed to preserve alignment. Each mmapped
-+ chunk is trailed by the first two fields of a fake next-chunk
-+ for sake of usage checks.
-+
-+*/
-+
-+struct malloc_chunk {
-+ size_t prev_foot; /* Size of previous chunk (if free). */
-+ size_t head; /* Size and inuse bits. */
-+ struct malloc_chunk* fd; /* double links -- used only if free. */
-+ struct malloc_chunk* bk;
-+};
-+
-+typedef struct malloc_chunk mchunk;
-+typedef struct malloc_chunk* mchunkptr;
-+typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */
-+typedef size_t bindex_t; /* Described below */
-+typedef unsigned int binmap_t; /* Described below */
-+typedef unsigned int flag_t; /* The type of various bit flag sets */
-+
-+/* ------------------- Chunks sizes and alignments ----------------------- */
-+
-+#define MCHUNK_SIZE (sizeof(mchunk))
-+
-+#if FOOTERS
-+#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
-+#else /* FOOTERS */
-+#define CHUNK_OVERHEAD (SIZE_T_SIZE)
-+#endif /* FOOTERS */
-+
-+/* MMapped chunks need a second word of overhead ... */
-+#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
-+/* ... and additional padding for fake next-chunk at foot */
-+#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES)
-+
-+/* The smallest size we can malloc is an aligned minimal chunk */
-+#define MIN_CHUNK_SIZE\
-+ ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
-+
-+/* conversion from malloc headers to user pointers, and back */
-+#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES))
-+#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES))
-+/* chunk associated with aligned address A */
-+#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
-+
-+/* Bounds on request (not chunk) sizes. */
-+#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2)
-+#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
-+
-+/* pad request bytes into a usable size */
-+#define pad_request(req) \
-+ (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
-+
-+/* pad request, checking for minimum (but not maximum) */
-+#define request2size(req) \
-+ (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
-+
-+
-+/* ------------------ Operations on head and foot fields ----------------- */
-+
-+/*
-+ The head field of a chunk is or'ed with PINUSE_BIT when previous
-+ adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
-+ use. If the chunk was obtained with mmap, the prev_foot field has
-+ IS_MMAPPED_BIT set, otherwise holding the offset of the base of the
-+ mmapped region to the base of the chunk.
-+*/
-+
-+#define PINUSE_BIT (SIZE_T_ONE)
-+#define CINUSE_BIT (SIZE_T_TWO)
-+#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
-+
-+/* Head value for fenceposts */
-+#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
-+
-+/* extraction of fields from head words */
-+#define cinuse(p) ((p)->head & CINUSE_BIT)
-+#define pinuse(p) ((p)->head & PINUSE_BIT)
-+#define chunksize(p) ((p)->head & ~(INUSE_BITS))
-+
-+#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
-+#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT)
-+
-+/* Treat space at ptr +/- offset as a chunk */
-+#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
-+#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
-+
-+/* Ptr to next or previous physical malloc_chunk. */
-+#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS)))
-+#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
-+
-+/* extract next chunk's pinuse bit */
-+#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
-+
-+/* Get/set size at footer */
-+#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
-+#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
-+
-+/* Set size, pinuse bit, and foot */
-+#define set_size_and_pinuse_of_free_chunk(p, s)\
-+ ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
-+
-+/* Set size, pinuse bit, foot, and clear next pinuse */
-+#define set_free_with_pinuse(p, s, n)\
-+ (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
-+
-+#define is_mmapped(p)\
-+ (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT))
-+
-+/* Get the internal overhead associated with chunk p */
-+#define overhead_for(p)\
-+ (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
-+
-+/* Return true if malloced space is not necessarily cleared */
-+#if MMAP_CLEARS
-+#define calloc_must_clear(p) (!is_mmapped(p))
-+#else /* MMAP_CLEARS */
-+#define calloc_must_clear(p) (1)
-+#endif /* MMAP_CLEARS */
-+
-+/* ---------------------- Overlaid data structures ----------------------- */
-+
-+/*
-+ When chunks are not in use, they are treated as nodes of either
-+ lists or trees.
-+
-+ "Small" chunks are stored in circular doubly-linked lists, and look
-+ like this:
-+
-+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Size of previous chunk |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ `head:' | Size of chunk, in bytes |P|
-+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Forward pointer to next chunk in list |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Back pointer to previous chunk in list |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Unused space (may be 0 bytes long) .
-+ . .
-+ . |
-+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ `foot:' | Size of chunk, in bytes |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+
-+ Larger chunks are kept in a form of bitwise digital trees (aka
-+ tries) keyed on chunksizes. Because malloc_tree_chunks are only for
-+ free chunks greater than 256 bytes, their size doesn't impose any
-+ constraints on user chunk sizes. Each node looks like:
-+
-+ chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Size of previous chunk |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ `head:' | Size of chunk, in bytes |P|
-+ mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Forward pointer to next chunk of same size |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Back pointer to previous chunk of same size |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Pointer to left child (child[0]) |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Pointer to right child (child[1]) |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Pointer to parent |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | bin index of this chunk |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ | Unused space .
-+ . |
-+nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+ `foot:' | Size of chunk, in bytes |
-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-+
-+ Each tree holding treenodes is a tree of unique chunk sizes. Chunks
-+ of the same size are arranged in a circularly-linked list, with only
-+ the oldest chunk (the next to be used, in our FIFO ordering)
-+ actually in the tree. (Tree members are distinguished by a non-null
-+ parent pointer.) If a chunk with the same size an an existing node
-+ is inserted, it is linked off the existing node using pointers that
-+ work in the same way as fd/bk pointers of small chunks.
-+
-+ Each tree contains a power of 2 sized range of chunk sizes (the
-+ smallest is 0x100 <= x < 0x180), which is is divided in half at each
-+ tree level, with the chunks in the smaller half of the range (0x100
-+ <= x < 0x140 for the top nose) in the left subtree and the larger
-+ half (0x140 <= x < 0x180) in the right subtree. This is, of course,
-+ done by inspecting individual bits.
-+
-+ Using these rules, each node's left subtree contains all smaller
-+ sizes than its right subtree. However, the node at the root of each
-+ subtree has no particular ordering relationship to either. (The
-+ dividing line between the subtree sizes is based on trie relation.)
-+ If we remove the last chunk of a given size from the interior of the
-+ tree, we need to replace it with a leaf node. The tree ordering
-+ rules permit a node to be replaced by any leaf below it.
-+
-+ The smallest chunk in a tree (a common operation in a best-fit
-+ allocator) can be found by walking a path to the leftmost leaf in
-+ the tree. Unlike a usual binary tree, where we follow left child
-+ pointers until we reach a null, here we follow the right child
-+ pointer any time the left one is null, until we reach a leaf with
-+ both child pointers null. The smallest chunk in the tree will be
-+ somewhere along that path.
-+
-+ The worst case number of steps to add, find, or remove a node is
-+ bounded by the number of bits differentiating chunks within
-+ bins. Under current bin calculations, this ranges from 6 up to 21
-+ (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case
-+ is of course much better.
-+*/
-+
-+struct malloc_tree_chunk {
-+ /* The first four fields must be compatible with malloc_chunk */
-+ size_t prev_foot;
-+ size_t head;
-+ struct malloc_tree_chunk* fd;
-+ struct malloc_tree_chunk* bk;
-+
-+ struct malloc_tree_chunk* child[2];
-+ struct malloc_tree_chunk* parent;
-+ bindex_t index;
-+};
-+
-+typedef struct malloc_tree_chunk tchunk;
-+typedef struct malloc_tree_chunk* tchunkptr;
-+typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
-+
-+/* A little helper macro for trees */
-+#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
-+
-+/* ----------------------------- Segments -------------------------------- */
-+
-+/*
-+ Each malloc space may include non-contiguous segments, held in a
-+ list headed by an embedded malloc_segment record representing the
-+ top-most space. Segments also include flags holding properties of
-+ the space. Large chunks that are directly allocated by mmap are not
-+ included in this list. They are instead independently created and
-+ destroyed without otherwise keeping track of them.
-+
-+ Segment management mainly comes into play for spaces allocated by
-+ MMAP. Any call to MMAP might or might not return memory that is
-+ adjacent to an existing segment. MORECORE normally contiguously
-+ extends the current space, so this space is almost always adjacent,
-+ which is simpler and faster to deal with. (This is why MORECORE is
-+ used preferentially to MMAP when both are available -- see
-+ sys_alloc.) When allocating using MMAP, we don't use any of the
-+ hinting mechanisms (inconsistently) supported in various
-+ implementations of unix mmap, or distinguish reserving from
-+ committing memory. Instead, we just ask for space, and exploit
-+ contiguity when we get it. It is probably possible to do
-+ better than this on some systems, but no general scheme seems
-+ to be significantly better.
-+
-+ Management entails a simpler variant of the consolidation scheme
-+ used for chunks to reduce fragmentation -- new adjacent memory is
-+ normally prepended or appended to an existing segment. However,
-+ there are limitations compared to chunk consolidation that mostly
-+ reflect the fact that segment processing is relatively infrequent
-+ (occurring only when getting memory from system) and that we
-+ don't expect to have huge numbers of segments:
-+
-+ * Segments are not indexed, so traversal requires linear scans. (It
-+ would be possible to index these, but is not worth the extra
-+ overhead and complexity for most programs on most platforms.)
-+ * New segments are only appended to old ones when holding top-most
-+ memory; if they cannot be prepended to others, they are held in
-+ different segments.
-+
-+ Except for the top-most segment of an mstate, each segment record
-+ is kept at the tail of its segment. Segments are added by pushing
-+ segment records onto the list headed by &mstate.seg for the
-+ containing mstate.
-+
-+ Segment flags control allocation/merge/deallocation policies:
-+ * If EXTERN_BIT set, then we did not allocate this segment,
-+ and so should not try to deallocate or merge with others.
-+ (This currently holds only for the initial segment passed
-+ into create_mspace_with_base.)
-+ * If IS_MMAPPED_BIT set, the segment may be merged with
-+ other surrounding mmapped segments and trimmed/de-allocated
-+ using munmap.
-+ * If neither bit is set, then the segment was obtained using
-+ MORECORE so can be merged with surrounding MORECORE'd segments
-+ and deallocated/trimmed using MORECORE with negative arguments.
-+*/
-+
-+struct malloc_segment {
-+ char* base; /* base address */
-+ size_t size; /* allocated size */
-+ struct malloc_segment* next; /* ptr to next segment */
-+#if FFI_MMAP_EXEC_WRIT
-+ /* The mmap magic is supposed to store the address of the executable
-+ segment at the very end of the requested block. */
-+
-+# define mmap_exec_offset(b,s) (*(ptrdiff_t*)((b)+(s)-sizeof(ptrdiff_t)))
-+
-+ /* We can only merge segments if their corresponding executable
-+ segments are at identical offsets. */
-+# define check_segment_merge(S,b,s) \
-+ (mmap_exec_offset((b),(s)) == (S)->exec_offset)
-+
-+# define add_segment_exec_offset(p,S) ((char*)(p) + (S)->exec_offset)
-+# define sub_segment_exec_offset(p,S) ((char*)(p) - (S)->exec_offset)
-+
-+ /* The removal of sflags only works with HAVE_MORECORE == 0. */
-+
-+# define get_segment_flags(S) (IS_MMAPPED_BIT)
-+# define set_segment_flags(S,v) \
-+ (((v) != IS_MMAPPED_BIT) ? (ABORT, (v)) : \
-+ (((S)->exec_offset = \
-+ mmap_exec_offset((S)->base, (S)->size)), \
-+ (mmap_exec_offset((S)->base + (S)->exec_offset, (S)->size) != \
-+ (S)->exec_offset) ? (ABORT, (v)) : \
-+ (mmap_exec_offset((S)->base, (S)->size) = 0), (v)))
-+
-+ /* We use an offset here, instead of a pointer, because then, when
-+ base changes, we don't have to modify this. On architectures
-+ with segmented addresses, this might not work. */
-+ ptrdiff_t exec_offset;
-+#else
-+
-+# define get_segment_flags(S) ((S)->sflags)
-+# define set_segment_flags(S,v) ((S)->sflags = (v))
-+# define check_segment_merge(S,b,s) (1)
-+
-+ flag_t sflags; /* mmap and extern flag */
-+#endif
-+};
-+
-+#define is_mmapped_segment(S) (get_segment_flags(S) & IS_MMAPPED_BIT)
-+#define is_extern_segment(S) (get_segment_flags(S) & EXTERN_BIT)
-+
-+typedef struct malloc_segment msegment;
-+typedef struct malloc_segment* msegmentptr;
-+
-+/* ---------------------------- malloc_state ----------------------------- */
-+
-+/*
-+ A malloc_state holds all of the bookkeeping for a space.
-+ The main fields are:
-+
-+ Top
-+ The topmost chunk of the currently active segment. Its size is
-+ cached in topsize. The actual size of topmost space is
-+ topsize+TOP_FOOT_SIZE, which includes space reserved for adding
-+ fenceposts and segment records if necessary when getting more
-+ space from the system. The size at which to autotrim top is
-+ cached from mparams in trim_check, except that it is disabled if
-+ an autotrim fails.
-+
-+ Designated victim (dv)
-+ This is the preferred chunk for servicing small requests that
-+ don't have exact fits. It is normally the chunk split off most
-+ recently to service another small request. Its size is cached in
-+ dvsize. The link fields of this chunk are not maintained since it
-+ is not kept in a bin.
-+
-+ SmallBins
-+ An array of bin headers for free chunks. These bins hold chunks
-+ with sizes less than MIN_LARGE_SIZE bytes. Each bin contains
-+ chunks of all the same size, spaced 8 bytes apart. To simplify
-+ use in double-linked lists, each bin header acts as a malloc_chunk
-+ pointing to the real first node, if it exists (else pointing to
-+ itself). This avoids special-casing for headers. But to avoid
-+ waste, we allocate only the fd/bk pointers of bins, and then use
-+ repositioning tricks to treat these as the fields of a chunk.
-+
-+ TreeBins
-+ Treebins are pointers to the roots of trees holding a range of
-+ sizes. There are 2 equally spaced treebins for each power of two
-+ from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything
-+ larger.
-+
-+ Bin maps
-+ There is one bit map for small bins ("smallmap") and one for
-+ treebins ("treemap). Each bin sets its bit when non-empty, and
-+ clears the bit when empty. Bit operations are then used to avoid
-+ bin-by-bin searching -- nearly all "search" is done without ever
-+ looking at bins that won't be selected. The bit maps
-+ conservatively use 32 bits per map word, even if on 64bit system.
-+ For a good description of some of the bit-based techniques used
-+ here, see Henry S. Warren Jr's book "Hacker's Delight" (and
-+ supplement at http://hackersdelight.org/). Many of these are
-+ intended to reduce the branchiness of paths through malloc etc, as
-+ well as to reduce the number of memory locations read or written.
-+
-+ Segments
-+ A list of segments headed by an embedded malloc_segment record
-+ representing the initial space.
-+
-+ Address check support
-+ The least_addr field is the least address ever obtained from
-+ MORECORE or MMAP. Attempted frees and reallocs of any address less
-+ than this are trapped (unless INSECURE is defined).
-+
-+ Magic tag
-+ A cross-check field that should always hold same value as mparams.magic.
-+
-+ Flags
-+ Bits recording whether to use MMAP, locks, or contiguous MORECORE
-+
-+ Statistics
-+ Each space keeps track of current and maximum system memory
-+ obtained via MORECORE or MMAP.
-+
-+ Locking
-+ If USE_LOCKS is defined, the "mutex" lock is acquired and released
-+ around every public call using this mspace.
-+*/
-+
-+/* Bin types, widths and sizes */
-+#define NSMALLBINS (32U)
-+#define NTREEBINS (32U)
-+#define SMALLBIN_SHIFT (3U)
-+#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
-+#define TREEBIN_SHIFT (8U)
-+#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
-+#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
-+#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
-+
-+struct malloc_state {
-+ binmap_t smallmap;
-+ binmap_t treemap;
-+ size_t dvsize;
-+ size_t topsize;
-+ char* least_addr;
-+ mchunkptr dv;
-+ mchunkptr top;
-+ size_t trim_check;
-+ size_t magic;
-+ mchunkptr smallbins[(NSMALLBINS+1)*2];
-+ tbinptr treebins[NTREEBINS];
-+ size_t footprint;
-+ size_t max_footprint;
-+ flag_t mflags;
-+#if USE_LOCKS
-+ MLOCK_T mutex; /* locate lock among fields that rarely change */
-+#endif /* USE_LOCKS */
-+ msegment seg;
-+};
-+
-+typedef struct malloc_state* mstate;
-+
-+/* ------------- Global malloc_state and malloc_params ------------------- */
-+
-+/*
-+ malloc_params holds global properties, including those that can be
-+ dynamically set using mallopt. There is a single instance, mparams,
-+ initialized in init_mparams.
-+*/
-+
-+struct malloc_params {
-+ size_t magic;
-+ size_t page_size;
-+ size_t granularity;
-+ size_t mmap_threshold;
-+ size_t trim_threshold;
-+ flag_t default_mflags;
-+};
-+
-+static struct malloc_params mparams;
-+
-+/* The global malloc_state used for all non-"mspace" calls */
-+static struct malloc_state _gm_;
-+#define gm (&_gm_)
-+#define is_global(M) ((M) == &_gm_)
-+#define is_initialized(M) ((M)->top != 0)
-+
-+/* -------------------------- system alloc setup ------------------------- */
-+
-+/* Operations on mflags */
-+
-+#define use_lock(M) ((M)->mflags & USE_LOCK_BIT)
-+#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT)
-+#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT)
-+
-+#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT)
-+#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT)
-+#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT)
-+
-+#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT)
-+#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT)
-+
-+#define set_lock(M,L)\
-+ ((M)->mflags = (L)?\
-+ ((M)->mflags | USE_LOCK_BIT) :\
-+ ((M)->mflags & ~USE_LOCK_BIT))
-+
-+/* page-align a size */
-+#define page_align(S)\
-+ (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE))
-+
-+/* granularity-align a size */
-+#define granularity_align(S)\
-+ (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE))
-+
-+#define is_page_aligned(S)\
-+ (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0)
-+#define is_granularity_aligned(S)\
-+ (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0)
-+
-+/* True if segment S holds address A */
-+#define segment_holds(S, A)\
-+ ((char*)(A) >= S->base && (char*)(A) < S->base + S->size)
-+
-+/* Return segment holding given address */
-+static msegmentptr segment_holding(mstate m, char* addr) {
-+ msegmentptr sp = &m->seg;
-+ for (;;) {
-+ if (addr >= sp->base && addr < sp->base + sp->size)
-+ return sp;
-+ if ((sp = sp->next) == 0)
-+ return 0;
-+ }
-+}
-+
-+/* Return true if segment contains a segment link */
-+static int has_segment_link(mstate m, msegmentptr ss) {
-+ msegmentptr sp = &m->seg;
-+ for (;;) {
-+ if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size)
-+ return 1;
-+ if ((sp = sp->next) == 0)
-+ return 0;
-+ }
-+}
-+
-+#ifndef MORECORE_CANNOT_TRIM
-+#define should_trim(M,s) ((s) > (M)->trim_check)
-+#else /* MORECORE_CANNOT_TRIM */
-+#define should_trim(M,s) (0)
-+#endif /* MORECORE_CANNOT_TRIM */
-+
-+/*
-+ TOP_FOOT_SIZE is padding at the end of a segment, including space
-+ that may be needed to place segment records and fenceposts when new
-+ noncontiguous segments are added.
-+*/
-+#define TOP_FOOT_SIZE\
-+ (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
-+
-+
-+/* ------------------------------- Hooks -------------------------------- */
-+
-+/*
-+ PREACTION should be defined to return 0 on success, and nonzero on
-+ failure. If you are not using locking, you can redefine these to do
-+ anything you like.
-+*/
-+
-+#if USE_LOCKS
-+
-+/* Ensure locks are initialized */
-+#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams())
-+
-+#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0)
-+#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); }
-+#else /* USE_LOCKS */
-+
-+#ifndef PREACTION
-+#define PREACTION(M) (0)
-+#endif /* PREACTION */
-+
-+#ifndef POSTACTION
-+#define POSTACTION(M)
-+#endif /* POSTACTION */
-+
-+#endif /* USE_LOCKS */
-+
-+/*
-+ CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses.
-+ USAGE_ERROR_ACTION is triggered on detected bad frees and
-+ reallocs. The argument p is an address that might have triggered the
-+ fault. It is ignored by the two predefined actions, but might be
-+ useful in custom actions that try to help diagnose errors.
-+*/
-+
-+#if PROCEED_ON_ERROR
-+
-+/* A count of the number of corruption errors causing resets */
-+int malloc_corruption_error_count;
-+
-+/* default corruption action */
-+static void reset_on_error(mstate m);
-+
-+#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m)
-+#define USAGE_ERROR_ACTION(m, p)
-+
-+#else /* PROCEED_ON_ERROR */
-+
-+#ifndef CORRUPTION_ERROR_ACTION
-+#define CORRUPTION_ERROR_ACTION(m) ABORT
-+#endif /* CORRUPTION_ERROR_ACTION */
-+
-+#ifndef USAGE_ERROR_ACTION
-+#define USAGE_ERROR_ACTION(m,p) ABORT
-+#endif /* USAGE_ERROR_ACTION */
-+
-+#endif /* PROCEED_ON_ERROR */
-+
-+/* -------------------------- Debugging setup ---------------------------- */
-+
-+#if ! DEBUG
-+
-+#define check_free_chunk(M,P)
-+#define check_inuse_chunk(M,P)
-+#define check_malloced_chunk(M,P,N)
-+#define check_mmapped_chunk(M,P)
-+#define check_malloc_state(M)
-+#define check_top_chunk(M,P)
-+
-+#else /* DEBUG */
-+#define check_free_chunk(M,P) do_check_free_chunk(M,P)
-+#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P)
-+#define check_top_chunk(M,P) do_check_top_chunk(M,P)
-+#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N)
-+#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P)
-+#define check_malloc_state(M) do_check_malloc_state(M)
-+
-+static void do_check_any_chunk(mstate m, mchunkptr p);
-+static void do_check_top_chunk(mstate m, mchunkptr p);
-+static void do_check_mmapped_chunk(mstate m, mchunkptr p);
-+static void do_check_inuse_chunk(mstate m, mchunkptr p);
-+static void do_check_free_chunk(mstate m, mchunkptr p);
-+static void do_check_malloced_chunk(mstate m, void* mem, size_t s);
-+static void do_check_tree(mstate m, tchunkptr t);
-+static void do_check_treebin(mstate m, bindex_t i);
-+static void do_check_smallbin(mstate m, bindex_t i);
-+static void do_check_malloc_state(mstate m);
-+static int bin_find(mstate m, mchunkptr x);
-+static size_t traverse_and_check(mstate m);
-+#endif /* DEBUG */
-+
-+/* ---------------------------- Indexing Bins ---------------------------- */
-+
-+#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
-+#define small_index(s) ((s) >> SMALLBIN_SHIFT)
-+#define small_index2size(i) ((i) << SMALLBIN_SHIFT)
-+#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
-+
-+/* addressing by index. See above about smallbin repositioning */
-+#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))
-+#define treebin_at(M,i) (&((M)->treebins[i]))
-+
-+/* assign tree index for size S to variable I */
-+#if defined(__GNUC__) && defined(i386)
-+#define compute_tree_index(S, I)\
-+{\
-+ size_t X = S >> TREEBIN_SHIFT;\
-+ if (X == 0)\
-+ I = 0;\
-+ else if (X > 0xFFFF)\
-+ I = NTREEBINS-1;\
-+ else {\
-+ unsigned int K;\
-+ __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\
-+ I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
-+ }\
-+}
-+#else /* GNUC */
-+#define compute_tree_index(S, I)\
-+{\
-+ size_t X = S >> TREEBIN_SHIFT;\
-+ if (X == 0)\
-+ I = 0;\
-+ else if (X > 0xFFFF)\
-+ I = NTREEBINS-1;\
-+ else {\
-+ unsigned int Y = (unsigned int)X;\
-+ unsigned int N = ((Y - 0x100) >> 16) & 8;\
-+ unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\
-+ N += K;\
-+ N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\
-+ K = 14 - N + ((Y <<= K) >> 15);\
-+ I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\
-+ }\
-+}
-+#endif /* GNUC */
-+
-+/* Bit representing maximum resolved size in a treebin at i */
-+#define bit_for_tree_index(i) \
-+ (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
-+
-+/* Shift placing maximum resolved bit in a treebin at i as sign bit */
-+#define leftshift_for_tree_index(i) \
-+ ((i == NTREEBINS-1)? 0 : \
-+ ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
-+
-+/* The size of the smallest chunk held in bin with index i */
-+#define minsize_for_tree_index(i) \
-+ ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
-+ (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
-+
-+
-+/* ------------------------ Operations on bin maps ----------------------- */
-+
-+/* bit corresponding to given index */
-+#define idx2bit(i) ((binmap_t)(1) << (i))
-+
-+/* Mark/Clear bits with given index */
-+#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
-+#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
-+#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
-+
-+#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
-+#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
-+#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
-+
-+/* index corresponding to given bit */
-+
-+#if defined(__GNUC__) && defined(i386)
-+#define compute_bit2idx(X, I)\
-+{\
-+ unsigned int J;\
-+ __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\
-+ I = (bindex_t)J;\
-+}
-+
-+#else /* GNUC */
-+#if USE_BUILTIN_FFS
-+#define compute_bit2idx(X, I) I = ffs(X)-1
-+
-+#else /* USE_BUILTIN_FFS */
-+#define compute_bit2idx(X, I)\
-+{\
-+ unsigned int Y = X - 1;\
-+ unsigned int K = Y >> (16-4) & 16;\
-+ unsigned int N = K; Y >>= K;\
-+ N += K = Y >> (8-3) & 8; Y >>= K;\
-+ N += K = Y >> (4-2) & 4; Y >>= K;\
-+ N += K = Y >> (2-1) & 2; Y >>= K;\
-+ N += K = Y >> (1-0) & 1; Y >>= K;\
-+ I = (bindex_t)(N + Y);\
-+}
-+#endif /* USE_BUILTIN_FFS */
-+#endif /* GNUC */
-+
-+/* isolate the least set bit of a bitmap */
-+#define least_bit(x) ((x) & -(x))
-+
-+/* mask with all bits to left of least bit of x on */
-+#define left_bits(x) ((x<<1) | -(x<<1))
-+
-+/* mask with all bits to left of or equal to least bit of x on */
-+#define same_or_left_bits(x) ((x) | -(x))
-+
-+
-+/* ----------------------- Runtime Check Support ------------------------- */
-+
-+/*
-+ For security, the main invariant is that malloc/free/etc never
-+ writes to a static address other than malloc_state, unless static
-+ malloc_state itself has been corrupted, which cannot occur via
-+ malloc (because of these checks). In essence this means that we
-+ believe all pointers, sizes, maps etc held in malloc_state, but
-+ check all of those linked or offsetted from other embedded data
-+ structures. These checks are interspersed with main code in a way
-+ that tends to minimize their run-time cost.
-+
-+ When FOOTERS is defined, in addition to range checking, we also
-+ verify footer fields of inuse chunks, which can be used guarantee
-+ that the mstate controlling malloc/free is intact. This is a
-+ streamlined version of the approach described by William Robertson
-+ et al in "Run-time Detection of Heap-based Overflows" LISA'03
-+ http://www.usenix.org/events/lisa03/tech/robertson.html The footer
-+ of an inuse chunk holds the xor of its mstate and a random seed,
-+ that is checked upon calls to free() and realloc(). This is
-+ (probablistically) unguessable from outside the program, but can be
-+ computed by any code successfully malloc'ing any chunk, so does not
-+ itself provide protection against code that has already broken
-+ security through some other means. Unlike Robertson et al, we
-+ always dynamically check addresses of all offset chunks (previous,
-+ next, etc). This turns out to be cheaper than relying on hashes.
-+*/
-+
-+#if !INSECURE
-+/* Check if address a is at least as high as any from MORECORE or MMAP */
-+#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
-+/* Check if address of next chunk n is higher than base chunk p */
-+#define ok_next(p, n) ((char*)(p) < (char*)(n))
-+/* Check if p has its cinuse bit on */
-+#define ok_cinuse(p) cinuse(p)
-+/* Check if p has its pinuse bit on */
-+#define ok_pinuse(p) pinuse(p)
-+
-+#else /* !INSECURE */
-+#define ok_address(M, a) (1)
-+#define ok_next(b, n) (1)
-+#define ok_cinuse(p) (1)
-+#define ok_pinuse(p) (1)
-+#endif /* !INSECURE */
-+
-+#if (FOOTERS && !INSECURE)
-+/* Check if (alleged) mstate m has expected magic field */
-+#define ok_magic(M) ((M)->magic == mparams.magic)
-+#else /* (FOOTERS && !INSECURE) */
-+#define ok_magic(M) (1)
-+#endif /* (FOOTERS && !INSECURE) */
-+
-+
-+/* In gcc, use __builtin_expect to minimize impact of checks */
-+#if !INSECURE
-+#if defined(__GNUC__) && __GNUC__ >= 3
-+#define RTCHECK(e) __builtin_expect(e, 1)
-+#else /* GNUC */
-+#define RTCHECK(e) (e)
-+#endif /* GNUC */
-+#else /* !INSECURE */
-+#define RTCHECK(e) (1)
-+#endif /* !INSECURE */
-+
-+/* macros to set up inuse chunks with or without footers */
-+
-+#if !FOOTERS
-+
-+#define mark_inuse_foot(M,p,s)
-+
-+/* Set cinuse bit and pinuse bit of next chunk */
-+#define set_inuse(M,p,s)\
-+ ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
-+ ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
-+
-+/* Set cinuse and pinuse of this chunk and pinuse of next chunk */
-+#define set_inuse_and_pinuse(M,p,s)\
-+ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
-+ ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT)
-+
-+/* Set size, cinuse and pinuse bit of this chunk */
-+#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
-+ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
-+
-+#else /* FOOTERS */
-+
-+/* Set foot of inuse chunk to be xor of mstate and seed */
-+#define mark_inuse_foot(M,p,s)\
-+ (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
-+
-+#define get_mstate_for(p)\
-+ ((mstate)(((mchunkptr)((char*)(p) +\
-+ (chunksize(p))))->prev_foot ^ mparams.magic))
-+
-+#define set_inuse(M,p,s)\
-+ ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
-+ (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \
-+ mark_inuse_foot(M,p,s))
-+
-+#define set_inuse_and_pinuse(M,p,s)\
-+ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
-+ (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\
-+ mark_inuse_foot(M,p,s))
-+
-+#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
-+ ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
-+ mark_inuse_foot(M, p, s))
-+
-+#endif /* !FOOTERS */
-+
-+/* ---------------------------- setting mparams -------------------------- */
-+
-+/* Initialize mparams */
-+static int init_mparams(void) {
-+ if (mparams.page_size == 0) {
-+ size_t s;
-+
-+ mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD;
-+ mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD;
-+#if MORECORE_CONTIGUOUS
-+ mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT;
-+#else /* MORECORE_CONTIGUOUS */
-+ mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT;
-+#endif /* MORECORE_CONTIGUOUS */
-+
-+#if (FOOTERS && !INSECURE)
-+ {
-+#if USE_DEV_RANDOM
-+ int fd;
-+ unsigned char buf[sizeof(size_t)];
-+ /* Try to use /dev/urandom, else fall back on using time */
-+ if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 &&
-+ read(fd, buf, sizeof(buf)) == sizeof(buf)) {
-+ s = *((size_t *) buf);
-+ close(fd);
-+ }
-+ else
-+#endif /* USE_DEV_RANDOM */
-+ s = (size_t)(time(0) ^ (size_t)0x55555555U);
-+
-+ s |= (size_t)8U; /* ensure nonzero */
-+ s &= ~(size_t)7U; /* improve chances of fault for bad values */
-+
-+ }
-+#else /* (FOOTERS && !INSECURE) */
-+ s = (size_t)0x58585858U;
-+#endif /* (FOOTERS && !INSECURE) */
-+ ACQUIRE_MAGIC_INIT_LOCK();
-+ if (mparams.magic == 0) {
-+ mparams.magic = s;
-+ /* Set up lock for main malloc area */
-+ INITIAL_LOCK(&gm->mutex);
-+ gm->mflags = mparams.default_mflags;
-+ }
-+ RELEASE_MAGIC_INIT_LOCK();
-+
-+#if !defined(WIN32) && !defined(__OS2__)
-+ mparams.page_size = malloc_getpagesize;
-+ mparams.granularity = ((DEFAULT_GRANULARITY != 0)?
-+ DEFAULT_GRANULARITY : mparams.page_size);
-+#elif defined (__OS2__)
-+ /* if low-memory is used, os2munmap() would break
-+ if it were anything other than 64k */
-+ mparams.page_size = 4096u;
-+ mparams.granularity = 65536u;
-+#else /* WIN32 */
-+ {
-+ SYSTEM_INFO system_info;
-+ GetSystemInfo(&system_info);
-+ mparams.page_size = system_info.dwPageSize;
-+ mparams.granularity = system_info.dwAllocationGranularity;
-+ }
-+#endif /* WIN32 */
-+
-+ /* Sanity-check configuration:
-+ size_t must be unsigned and as wide as pointer type.
-+ ints must be at least 4 bytes.
-+ alignment must be at least 8.
-+ Alignment, min chunk size, and page size must all be powers of 2.
-+ */
-+ if ((sizeof(size_t) != sizeof(char*)) ||
-+ (MAX_SIZE_T < MIN_CHUNK_SIZE) ||
-+ (sizeof(int) < 4) ||
-+ (MALLOC_ALIGNMENT < (size_t)8U) ||
-+ ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) ||
-+ ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) ||
-+ ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) ||
-+ ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0))
-+ ABORT;
-+ }
-+ return 0;
-+}
-+
-+/* support for mallopt */
-+static int change_mparam(int param_number, int value) {
-+ size_t val = (size_t)value;
-+ init_mparams();
-+ switch(param_number) {
-+ case M_TRIM_THRESHOLD:
-+ mparams.trim_threshold = val;
-+ return 1;
-+ case M_GRANULARITY:
-+ if (val >= mparams.page_size && ((val & (val-1)) == 0)) {
-+ mparams.granularity = val;
-+ return 1;
-+ }
-+ else
-+ return 0;
-+ case M_MMAP_THRESHOLD:
-+ mparams.mmap_threshold = val;
-+ return 1;
-+ default:
-+ return 0;
-+ }
-+}
-+
-+#if DEBUG
-+/* ------------------------- Debugging Support --------------------------- */
-+
-+/* Check properties of any chunk, whether free, inuse, mmapped etc */
-+static void do_check_any_chunk(mstate m, mchunkptr p) {
-+ assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
-+ assert(ok_address(m, p));
-+}
-+
-+/* Check properties of top chunk */
-+static void do_check_top_chunk(mstate m, mchunkptr p) {
-+ msegmentptr sp = segment_holding(m, (char*)p);
-+ size_t sz = chunksize(p);
-+ assert(sp != 0);
-+ assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
-+ assert(ok_address(m, p));
-+ assert(sz == m->topsize);
-+ assert(sz > 0);
-+ assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE);
-+ assert(pinuse(p));
-+ assert(!next_pinuse(p));
-+}
-+
-+/* Check properties of (inuse) mmapped chunks */
-+static void do_check_mmapped_chunk(mstate m, mchunkptr p) {
-+ size_t sz = chunksize(p);
-+ size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD);
-+ assert(is_mmapped(p));
-+ assert(use_mmap(m));
-+ assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD));
-+ assert(ok_address(m, p));
-+ assert(!is_small(sz));
-+ assert((len & (mparams.page_size-SIZE_T_ONE)) == 0);
-+ assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD);
-+ assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0);
-+}
-+
-+/* Check properties of inuse chunks */
-+static void do_check_inuse_chunk(mstate m, mchunkptr p) {
-+ do_check_any_chunk(m, p);
-+ assert(cinuse(p));
-+ assert(next_pinuse(p));
-+ /* If not pinuse and not mmapped, previous chunk has OK offset */
-+ assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p);
-+ if (is_mmapped(p))
-+ do_check_mmapped_chunk(m, p);
-+}
-+
-+/* Check properties of free chunks */
-+static void do_check_free_chunk(mstate m, mchunkptr p) {
-+ size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
-+ mchunkptr next = chunk_plus_offset(p, sz);
-+ do_check_any_chunk(m, p);
-+ assert(!cinuse(p));
-+ assert(!next_pinuse(p));
-+ assert (!is_mmapped(p));
-+ if (p != m->dv && p != m->top) {
-+ if (sz >= MIN_CHUNK_SIZE) {
-+ assert((sz & CHUNK_ALIGN_MASK) == 0);
-+ assert(is_aligned(chunk2mem(p)));
-+ assert(next->prev_foot == sz);
-+ assert(pinuse(p));
-+ assert (next == m->top || cinuse(next));
-+ assert(p->fd->bk == p);
-+ assert(p->bk->fd == p);
-+ }
-+ else /* markers are always of size SIZE_T_SIZE */
-+ assert(sz == SIZE_T_SIZE);
-+ }
-+}
-+
-+/* Check properties of malloced chunks at the point they are malloced */
-+static void do_check_malloced_chunk(mstate m, void* mem, size_t s) {
-+ if (mem != 0) {
-+ mchunkptr p = mem2chunk(mem);
-+ size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT);
-+ do_check_inuse_chunk(m, p);
-+ assert((sz & CHUNK_ALIGN_MASK) == 0);
-+ assert(sz >= MIN_CHUNK_SIZE);
-+ assert(sz >= s);
-+ /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */
-+ assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE));
-+ }
-+}
-+
-+/* Check a tree and its subtrees. */
-+static void do_check_tree(mstate m, tchunkptr t) {
-+ tchunkptr head = 0;
-+ tchunkptr u = t;
-+ bindex_t tindex = t->index;
-+ size_t tsize = chunksize(t);
-+ bindex_t idx;
-+ compute_tree_index(tsize, idx);
-+ assert(tindex == idx);
-+ assert(tsize >= MIN_LARGE_SIZE);
-+ assert(tsize >= minsize_for_tree_index(idx));
-+ assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1))));
-+
-+ do { /* traverse through chain of same-sized nodes */
-+ do_check_any_chunk(m, ((mchunkptr)u));
-+ assert(u->index == tindex);
-+ assert(chunksize(u) == tsize);
-+ assert(!cinuse(u));
-+ assert(!next_pinuse(u));
-+ assert(u->fd->bk == u);
-+ assert(u->bk->fd == u);
-+ if (u->parent == 0) {
-+ assert(u->child[0] == 0);
-+ assert(u->child[1] == 0);
-+ }
-+ else {
-+ assert(head == 0); /* only one node on chain has parent */
-+ head = u;
-+ assert(u->parent != u);
-+ assert (u->parent->child[0] == u ||
-+ u->parent->child[1] == u ||
-+ *((tbinptr*)(u->parent)) == u);
-+ if (u->child[0] != 0) {
-+ assert(u->child[0]->parent == u);
-+ assert(u->child[0] != u);
-+ do_check_tree(m, u->child[0]);
-+ }
-+ if (u->child[1] != 0) {
-+ assert(u->child[1]->parent == u);
-+ assert(u->child[1] != u);
-+ do_check_tree(m, u->child[1]);
-+ }
-+ if (u->child[0] != 0 && u->child[1] != 0) {
-+ assert(chunksize(u->child[0]) < chunksize(u->child[1]));
-+ }
-+ }
-+ u = u->fd;
-+ } while (u != t);
-+ assert(head != 0);
-+}
-+
-+/* Check all the chunks in a treebin. */
-+static void do_check_treebin(mstate m, bindex_t i) {
-+ tbinptr* tb = treebin_at(m, i);
-+ tchunkptr t = *tb;
-+ int empty = (m->treemap & (1U << i)) == 0;
-+ if (t == 0)
-+ assert(empty);
-+ if (!empty)
-+ do_check_tree(m, t);
-+}
-+
-+/* Check all the chunks in a smallbin. */
-+static void do_check_smallbin(mstate m, bindex_t i) {
-+ sbinptr b = smallbin_at(m, i);
-+ mchunkptr p = b->bk;
-+ unsigned int empty = (m->smallmap & (1U << i)) == 0;
-+ if (p == b)
-+ assert(empty);
-+ if (!empty) {
-+ for (; p != b; p = p->bk) {
-+ size_t size = chunksize(p);
-+ mchunkptr q;
-+ /* each chunk claims to be free */
-+ do_check_free_chunk(m, p);
-+ /* chunk belongs in bin */
-+ assert(small_index(size) == i);
-+ assert(p->bk == b || chunksize(p->bk) == chunksize(p));
-+ /* chunk is followed by an inuse chunk */
-+ q = next_chunk(p);
-+ if (q->head != FENCEPOST_HEAD)
-+ do_check_inuse_chunk(m, q);
-+ }
-+ }
-+}
-+
-+/* Find x in a bin. Used in other check functions. */
-+static int bin_find(mstate m, mchunkptr x) {
-+ size_t size = chunksize(x);
-+ if (is_small(size)) {
-+ bindex_t sidx = small_index(size);
-+ sbinptr b = smallbin_at(m, sidx);
-+ if (smallmap_is_marked(m, sidx)) {
-+ mchunkptr p = b;
-+ do {
-+ if (p == x)
-+ return 1;
-+ } while ((p = p->fd) != b);
-+ }
-+ }
-+ else {
-+ bindex_t tidx;
-+ compute_tree_index(size, tidx);
-+ if (treemap_is_marked(m, tidx)) {
-+ tchunkptr t = *treebin_at(m, tidx);
-+ size_t sizebits = size << leftshift_for_tree_index(tidx);
-+ while (t != 0 && chunksize(t) != size) {
-+ t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
-+ sizebits <<= 1;
-+ }
-+ if (t != 0) {
-+ tchunkptr u = t;
-+ do {
-+ if (u == (tchunkptr)x)
-+ return 1;
-+ } while ((u = u->fd) != t);
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* Traverse each chunk and check it; return total */
-+static size_t traverse_and_check(mstate m) {
-+ size_t sum = 0;
-+ if (is_initialized(m)) {
-+ msegmentptr s = &m->seg;
-+ sum += m->topsize + TOP_FOOT_SIZE;
-+ while (s != 0) {
-+ mchunkptr q = align_as_chunk(s->base);
-+ mchunkptr lastq = 0;
-+ assert(pinuse(q));
-+ while (segment_holds(s, q) &&
-+ q != m->top && q->head != FENCEPOST_HEAD) {
-+ sum += chunksize(q);
-+ if (cinuse(q)) {
-+ assert(!bin_find(m, q));
-+ do_check_inuse_chunk(m, q);
-+ }
-+ else {
-+ assert(q == m->dv || bin_find(m, q));
-+ assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */
-+ do_check_free_chunk(m, q);
-+ }
-+ lastq = q;
-+ q = next_chunk(q);
-+ }
-+ s = s->next;
-+ }
-+ }
-+ return sum;
-+}
-+
-+/* Check all properties of malloc_state. */
-+static void do_check_malloc_state(mstate m) {
-+ bindex_t i;
-+ size_t total;
-+ /* check bins */
-+ for (i = 0; i < NSMALLBINS; ++i)
-+ do_check_smallbin(m, i);
-+ for (i = 0; i < NTREEBINS; ++i)
-+ do_check_treebin(m, i);
-+
-+ if (m->dvsize != 0) { /* check dv chunk */
-+ do_check_any_chunk(m, m->dv);
-+ assert(m->dvsize == chunksize(m->dv));
-+ assert(m->dvsize >= MIN_CHUNK_SIZE);
-+ assert(bin_find(m, m->dv) == 0);
-+ }
-+
-+ if (m->top != 0) { /* check top chunk */
-+ do_check_top_chunk(m, m->top);
-+ assert(m->topsize == chunksize(m->top));
-+ assert(m->topsize > 0);
-+ assert(bin_find(m, m->top) == 0);
-+ }
-+
-+ total = traverse_and_check(m);
-+ assert(total <= m->footprint);
-+ assert(m->footprint <= m->max_footprint);
-+}
-+#endif /* DEBUG */
-+
-+/* ----------------------------- statistics ------------------------------ */
-+
-+#if !NO_MALLINFO
-+static struct mallinfo internal_mallinfo(mstate m) {
-+ struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-+ if (!PREACTION(m)) {
-+ check_malloc_state(m);
-+ if (is_initialized(m)) {
-+ size_t nfree = SIZE_T_ONE; /* top always free */
-+ size_t mfree = m->topsize + TOP_FOOT_SIZE;
-+ size_t sum = mfree;
-+ msegmentptr s = &m->seg;
-+ while (s != 0) {
-+ mchunkptr q = align_as_chunk(s->base);
-+ while (segment_holds(s, q) &&
-+ q != m->top && q->head != FENCEPOST_HEAD) {
-+ size_t sz = chunksize(q);
-+ sum += sz;
-+ if (!cinuse(q)) {
-+ mfree += sz;
-+ ++nfree;
-+ }
-+ q = next_chunk(q);
-+ }
-+ s = s->next;
-+ }
-+
-+ nm.arena = sum;
-+ nm.ordblks = nfree;
-+ nm.hblkhd = m->footprint - sum;
-+ nm.usmblks = m->max_footprint;
-+ nm.uordblks = m->footprint - mfree;
-+ nm.fordblks = mfree;
-+ nm.keepcost = m->topsize;
-+ }
-+
-+ POSTACTION(m);
-+ }
-+ return nm;
-+}
-+#endif /* !NO_MALLINFO */
-+
-+static void internal_malloc_stats(mstate m) {
-+ if (!PREACTION(m)) {
-+ size_t maxfp = 0;
-+ size_t fp = 0;
-+ size_t used = 0;
-+ check_malloc_state(m);
-+ if (is_initialized(m)) {
-+ msegmentptr s = &m->seg;
-+ maxfp = m->max_footprint;
-+ fp = m->footprint;
-+ used = fp - (m->topsize + TOP_FOOT_SIZE);
-+
-+ while (s != 0) {
-+ mchunkptr q = align_as_chunk(s->base);
-+ while (segment_holds(s, q) &&
-+ q != m->top && q->head != FENCEPOST_HEAD) {
-+ if (!cinuse(q))
-+ used -= chunksize(q);
-+ q = next_chunk(q);
-+ }
-+ s = s->next;
-+ }
-+ }
-+
-+ fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp));
-+ fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp));
-+ fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used));
-+
-+ POSTACTION(m);
-+ }
-+}
-+
-+/* ----------------------- Operations on smallbins ----------------------- */
-+
-+/*
-+ Various forms of linking and unlinking are defined as macros. Even
-+ the ones for trees, which are very long but have very short typical
-+ paths. This is ugly but reduces reliance on inlining support of
-+ compilers.
-+*/
-+
-+/* Link a free chunk into a smallbin */
-+#define insert_small_chunk(M, P, S) {\
-+ bindex_t I = small_index(S);\
-+ mchunkptr B = smallbin_at(M, I);\
-+ mchunkptr F = B;\
-+ assert(S >= MIN_CHUNK_SIZE);\
-+ if (!smallmap_is_marked(M, I))\
-+ mark_smallmap(M, I);\
-+ else if (RTCHECK(ok_address(M, B->fd)))\
-+ F = B->fd;\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+ B->fd = P;\
-+ F->bk = P;\
-+ P->fd = F;\
-+ P->bk = B;\
-+}
-+
-+/* Unlink a chunk from a smallbin */
-+#define unlink_small_chunk(M, P, S) {\
-+ mchunkptr F = P->fd;\
-+ mchunkptr B = P->bk;\
-+ bindex_t I = small_index(S);\
-+ assert(P != B);\
-+ assert(P != F);\
-+ assert(chunksize(P) == small_index2size(I));\
-+ if (F == B)\
-+ clear_smallmap(M, I);\
-+ else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\
-+ (B == smallbin_at(M,I) || ok_address(M, B)))) {\
-+ F->bk = B;\
-+ B->fd = F;\
-+ }\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+}
-+
-+/* Unlink the first chunk from a smallbin */
-+#define unlink_first_small_chunk(M, B, P, I) {\
-+ mchunkptr F = P->fd;\
-+ assert(P != B);\
-+ assert(P != F);\
-+ assert(chunksize(P) == small_index2size(I));\
-+ if (B == F)\
-+ clear_smallmap(M, I);\
-+ else if (RTCHECK(ok_address(M, F))) {\
-+ B->fd = F;\
-+ F->bk = B;\
-+ }\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+}
-+
-+/* Replace dv node, binning the old one */
-+/* Used only when dvsize known to be small */
-+#define replace_dv(M, P, S) {\
-+ size_t DVS = M->dvsize;\
-+ if (DVS != 0) {\
-+ mchunkptr DV = M->dv;\
-+ assert(is_small(DVS));\
-+ insert_small_chunk(M, DV, DVS);\
-+ }\
-+ M->dvsize = S;\
-+ M->dv = P;\
-+}
-+
-+/* ------------------------- Operations on trees ------------------------- */
-+
-+/* Insert chunk into tree */
-+#define insert_large_chunk(M, X, S) {\
-+ tbinptr* H;\
-+ bindex_t I;\
-+ compute_tree_index(S, I);\
-+ H = treebin_at(M, I);\
-+ X->index = I;\
-+ X->child[0] = X->child[1] = 0;\
-+ if (!treemap_is_marked(M, I)) {\
-+ mark_treemap(M, I);\
-+ *H = X;\
-+ X->parent = (tchunkptr)H;\
-+ X->fd = X->bk = X;\
-+ }\
-+ else {\
-+ tchunkptr T = *H;\
-+ size_t K = S << leftshift_for_tree_index(I);\
-+ for (;;) {\
-+ if (chunksize(T) != S) {\
-+ tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
-+ K <<= 1;\
-+ if (*C != 0)\
-+ T = *C;\
-+ else if (RTCHECK(ok_address(M, C))) {\
-+ *C = X;\
-+ X->parent = T;\
-+ X->fd = X->bk = X;\
-+ break;\
-+ }\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ break;\
-+ }\
-+ }\
-+ else {\
-+ tchunkptr F = T->fd;\
-+ if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\
-+ T->fd = F->bk = X;\
-+ X->fd = F;\
-+ X->bk = T;\
-+ X->parent = 0;\
-+ break;\
-+ }\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ break;\
-+ }\
-+ }\
-+ }\
-+ }\
-+}
-+
-+/*
-+ Unlink steps:
-+
-+ 1. If x is a chained node, unlink it from its same-sized fd/bk links
-+ and choose its bk node as its replacement.
-+ 2. If x was the last node of its size, but not a leaf node, it must
-+ be replaced with a leaf node (not merely one with an open left or
-+ right), to make sure that lefts and rights of descendants
-+ correspond properly to bit masks. We use the rightmost descendant
-+ of x. We could use any other leaf, but this is easy to locate and
-+ tends to counteract removal of leftmosts elsewhere, and so keeps
-+ paths shorter than minimally guaranteed. This doesn't loop much
-+ because on average a node in a tree is near the bottom.
-+ 3. If x is the base of a chain (i.e., has parent links) relink
-+ x's parent and children to x's replacement (or null if none).
-+*/
-+
-+#define unlink_large_chunk(M, X) {\
-+ tchunkptr XP = X->parent;\
-+ tchunkptr R;\
-+ if (X->bk != X) {\
-+ tchunkptr F = X->fd;\
-+ R = X->bk;\
-+ if (RTCHECK(ok_address(M, F))) {\
-+ F->bk = R;\
-+ R->fd = F;\
-+ }\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+ }\
-+ else {\
-+ tchunkptr* RP;\
-+ if (((R = *(RP = &(X->child[1]))) != 0) ||\
-+ ((R = *(RP = &(X->child[0]))) != 0)) {\
-+ tchunkptr* CP;\
-+ while ((*(CP = &(R->child[1])) != 0) ||\
-+ (*(CP = &(R->child[0])) != 0)) {\
-+ R = *(RP = CP);\
-+ }\
-+ if (RTCHECK(ok_address(M, RP)))\
-+ *RP = 0;\
-+ else {\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+ }\
-+ }\
-+ if (XP != 0) {\
-+ tbinptr* H = treebin_at(M, X->index);\
-+ if (X == *H) {\
-+ if ((*H = R) == 0) \
-+ clear_treemap(M, X->index);\
-+ }\
-+ else if (RTCHECK(ok_address(M, XP))) {\
-+ if (XP->child[0] == X) \
-+ XP->child[0] = R;\
-+ else \
-+ XP->child[1] = R;\
-+ }\
-+ else\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ if (R != 0) {\
-+ if (RTCHECK(ok_address(M, R))) {\
-+ tchunkptr C0, C1;\
-+ R->parent = XP;\
-+ if ((C0 = X->child[0]) != 0) {\
-+ if (RTCHECK(ok_address(M, C0))) {\
-+ R->child[0] = C0;\
-+ C0->parent = R;\
-+ }\
-+ else\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+ if ((C1 = X->child[1]) != 0) {\
-+ if (RTCHECK(ok_address(M, C1))) {\
-+ R->child[1] = C1;\
-+ C1->parent = R;\
-+ }\
-+ else\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+ }\
-+ else\
-+ CORRUPTION_ERROR_ACTION(M);\
-+ }\
-+ }\
-+}
-+
-+/* Relays to large vs small bin operations */
-+
-+#define insert_chunk(M, P, S)\
-+ if (is_small(S)) insert_small_chunk(M, P, S)\
-+ else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
-+
-+#define unlink_chunk(M, P, S)\
-+ if (is_small(S)) unlink_small_chunk(M, P, S)\
-+ else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
-+
-+
-+/* Relays to internal calls to malloc/free from realloc, memalign etc */
-+
-+#if ONLY_MSPACES
-+#define internal_malloc(m, b) mspace_malloc(m, b)
-+#define internal_free(m, mem) mspace_free(m,mem);
-+#else /* ONLY_MSPACES */
-+#if MSPACES
-+#define internal_malloc(m, b)\
-+ (m == gm)? dlmalloc(b) : mspace_malloc(m, b)
-+#define internal_free(m, mem)\
-+ if (m == gm) dlfree(mem); else mspace_free(m,mem);
-+#else /* MSPACES */
-+#define internal_malloc(m, b) dlmalloc(b)
-+#define internal_free(m, mem) dlfree(mem)
-+#endif /* MSPACES */
-+#endif /* ONLY_MSPACES */
-+
-+/* ----------------------- Direct-mmapping chunks ----------------------- */
-+
-+/*
-+ Directly mmapped chunks are set up with an offset to the start of
-+ the mmapped region stored in the prev_foot field of the chunk. This
-+ allows reconstruction of the required argument to MUNMAP when freed,
-+ and also allows adjustment of the returned chunk to meet alignment
-+ requirements (especially in memalign). There is also enough space
-+ allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain
-+ the PINUSE bit so frees can be checked.
-+*/
-+
-+/* Malloc using mmap */
-+static void* mmap_alloc(mstate m, size_t nb) {
-+ size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
-+ if (mmsize > nb) { /* Check for wrap around 0 */
-+ char* mm = (char*)(DIRECT_MMAP(mmsize));
-+ if (mm != CMFAIL) {
-+ size_t offset = align_offset(chunk2mem(mm));
-+ size_t psize = mmsize - offset - MMAP_FOOT_PAD;
-+ mchunkptr p = (mchunkptr)(mm + offset);
-+ p->prev_foot = offset | IS_MMAPPED_BIT;
-+ (p)->head = (psize|CINUSE_BIT);
-+ mark_inuse_foot(m, p, psize);
-+ chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
-+ chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
-+
-+ if (mm < m->least_addr)
-+ m->least_addr = mm;
-+ if ((m->footprint += mmsize) > m->max_footprint)
-+ m->max_footprint = m->footprint;
-+ assert(is_aligned(chunk2mem(p)));
-+ check_mmapped_chunk(m, p);
-+ return chunk2mem(p);
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* Realloc using mmap */
-+static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) {
-+ size_t oldsize = chunksize(oldp);
-+ if (is_small(nb)) /* Can't shrink mmap regions below small size */
-+ return 0;
-+ /* Keep old chunk if big enough but not too big */
-+ if (oldsize >= nb + SIZE_T_SIZE &&
-+ (oldsize - nb) <= (mparams.granularity << 1))
-+ return oldp;
-+ else {
-+ size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT;
-+ size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
-+ size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES +
-+ CHUNK_ALIGN_MASK);
-+ char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
-+ oldmmsize, newmmsize, 1);
-+ if (cp != CMFAIL) {
-+ mchunkptr newp = (mchunkptr)(cp + offset);
-+ size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
-+ newp->head = (psize|CINUSE_BIT);
-+ mark_inuse_foot(m, newp, psize);
-+ chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
-+ chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
-+
-+ if (cp < m->least_addr)
-+ m->least_addr = cp;
-+ if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
-+ m->max_footprint = m->footprint;
-+ check_mmapped_chunk(m, newp);
-+ return newp;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* -------------------------- mspace management -------------------------- */
-+
-+/* Initialize top chunk and its size */
-+static void init_top(mstate m, mchunkptr p, size_t psize) {
-+ /* Ensure alignment */
-+ size_t offset = align_offset(chunk2mem(p));
-+ p = (mchunkptr)((char*)p + offset);
-+ psize -= offset;
-+
-+ m->top = p;
-+ m->topsize = psize;
-+ p->head = psize | PINUSE_BIT;
-+ /* set size of fake trailing chunk holding overhead space only once */
-+ chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
-+ m->trim_check = mparams.trim_threshold; /* reset on each update */
-+}
-+
-+/* Initialize bins for a new mstate that is otherwise zeroed out */
-+static void init_bins(mstate m) {
-+ /* Establish circular links for smallbins */
-+ bindex_t i;
-+ for (i = 0; i < NSMALLBINS; ++i) {
-+ sbinptr bin = smallbin_at(m,i);
-+ bin->fd = bin->bk = bin;
-+ }
-+}
-+
-+#if PROCEED_ON_ERROR
-+
-+/* default corruption action */
-+static void reset_on_error(mstate m) {
-+ int i;
-+ ++malloc_corruption_error_count;
-+ /* Reinitialize fields to forget about all memory */
-+ m->smallbins = m->treebins = 0;
-+ m->dvsize = m->topsize = 0;
-+ m->seg.base = 0;
-+ m->seg.size = 0;
-+ m->seg.next = 0;
-+ m->top = m->dv = 0;
-+ for (i = 0; i < NTREEBINS; ++i)
-+ *treebin_at(m, i) = 0;
-+ init_bins(m);
-+}
-+#endif /* PROCEED_ON_ERROR */
-+
-+/* Allocate chunk and prepend remainder with chunk in successor base. */
-+static void* prepend_alloc(mstate m, char* newbase, char* oldbase,
-+ size_t nb) {
-+ mchunkptr p = align_as_chunk(newbase);
-+ mchunkptr oldfirst = align_as_chunk(oldbase);
-+ size_t psize = (char*)oldfirst - (char*)p;
-+ mchunkptr q = chunk_plus_offset(p, nb);
-+ size_t qsize = psize - nb;
-+ set_size_and_pinuse_of_inuse_chunk(m, p, nb);
-+
-+ assert((char*)oldfirst > (char*)q);
-+ assert(pinuse(oldfirst));
-+ assert(qsize >= MIN_CHUNK_SIZE);
-+
-+ /* consolidate remainder with first chunk of old base */
-+ if (oldfirst == m->top) {
-+ size_t tsize = m->topsize += qsize;
-+ m->top = q;
-+ q->head = tsize | PINUSE_BIT;
-+ check_top_chunk(m, q);
-+ }
-+ else if (oldfirst == m->dv) {
-+ size_t dsize = m->dvsize += qsize;
-+ m->dv = q;
-+ set_size_and_pinuse_of_free_chunk(q, dsize);
-+ }
-+ else {
-+ if (!cinuse(oldfirst)) {
-+ size_t nsize = chunksize(oldfirst);
-+ unlink_chunk(m, oldfirst, nsize);
-+ oldfirst = chunk_plus_offset(oldfirst, nsize);
-+ qsize += nsize;
-+ }
-+ set_free_with_pinuse(q, qsize, oldfirst);
-+ insert_chunk(m, q, qsize);
-+ check_free_chunk(m, q);
-+ }
-+
-+ check_malloced_chunk(m, chunk2mem(p), nb);
-+ return chunk2mem(p);
-+}
-+
-+
-+/* Add a segment to hold a new noncontiguous region */
-+static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
-+ /* Determine locations and sizes of segment, fenceposts, old top */
-+ char* old_top = (char*)m->top;
-+ msegmentptr oldsp = segment_holding(m, old_top);
-+ char* old_end = oldsp->base + oldsp->size;
-+ size_t ssize = pad_request(sizeof(struct malloc_segment));
-+ char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
-+ size_t offset = align_offset(chunk2mem(rawsp));
-+ char* asp = rawsp + offset;
-+ char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
-+ mchunkptr sp = (mchunkptr)csp;
-+ msegmentptr ss = (msegmentptr)(chunk2mem(sp));
-+ mchunkptr tnext = chunk_plus_offset(sp, ssize);
-+ mchunkptr p = tnext;
-+ int nfences = 0;
-+
-+ /* reset top to new space */
-+ init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
-+
-+ /* Set up segment record */
-+ assert(is_aligned(ss));
-+ set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
-+ *ss = m->seg; /* Push current record */
-+ m->seg.base = tbase;
-+ m->seg.size = tsize;
-+ (void)set_segment_flags(&m->seg, mmapped);
-+ m->seg.next = ss;
-+
-+ /* Insert trailing fenceposts */
-+ for (;;) {
-+ mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
-+ p->head = FENCEPOST_HEAD;
-+ ++nfences;
-+ if ((char*)(&(nextp->head)) < old_end)
-+ p = nextp;
-+ else
-+ break;
-+ }
-+ assert(nfences >= 2);
-+
-+ /* Insert the rest of old top into a bin as an ordinary free chunk */
-+ if (csp != old_top) {
-+ mchunkptr q = (mchunkptr)old_top;
-+ size_t psize = csp - old_top;
-+ mchunkptr tn = chunk_plus_offset(q, psize);
-+ set_free_with_pinuse(q, psize, tn);
-+ insert_chunk(m, q, psize);
-+ }
-+
-+ check_top_chunk(m, m->top);
-+}
-+
-+/* -------------------------- System allocation -------------------------- */
-+
-+/* Get memory from system using MORECORE or MMAP */
-+static void* sys_alloc(mstate m, size_t nb) {
-+ char* tbase = CMFAIL;
-+ size_t tsize = 0;
-+ flag_t mmap_flag = 0;
-+
-+ init_mparams();
-+
-+ /* Directly map large chunks */
-+ if (use_mmap(m) && nb >= mparams.mmap_threshold) {
-+ void* mem = mmap_alloc(m, nb);
-+ if (mem != 0)
-+ return mem;
-+ }
-+
-+ /*
-+ Try getting memory in any of three ways (in most-preferred to
-+ least-preferred order):
-+ 1. A call to MORECORE that can normally contiguously extend memory.
-+ (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or
-+ or main space is mmapped or a previous contiguous call failed)
-+ 2. A call to MMAP new space (disabled if not HAVE_MMAP).
-+ Note that under the default settings, if MORECORE is unable to
-+ fulfill a request, and HAVE_MMAP is true, then mmap is
-+ used as a noncontiguous system allocator. This is a useful backup
-+ strategy for systems with holes in address spaces -- in this case
-+ sbrk cannot contiguously expand the heap, but mmap may be able to
-+ find space.
-+ 3. A call to MORECORE that cannot usually contiguously extend memory.
-+ (disabled if not HAVE_MORECORE)
-+ */
-+
-+ if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) {
-+ char* br = CMFAIL;
-+ msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top);
-+ size_t asize = 0;
-+ ACQUIRE_MORECORE_LOCK();
-+
-+ if (ss == 0) { /* First time through or recovery */
-+ char* base = (char*)CALL_MORECORE(0);
-+ if (base != CMFAIL) {
-+ asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
-+ /* Adjust to end on a page boundary */
-+ if (!is_page_aligned(base))
-+ asize += (page_align((size_t)base) - (size_t)base);
-+ /* Can't call MORECORE if size is negative when treated as signed */
-+ if (asize < HALF_MAX_SIZE_T &&
-+ (br = (char*)(CALL_MORECORE(asize))) == base) {
-+ tbase = base;
-+ tsize = asize;
-+ }
-+ }
-+ }
-+ else {
-+ /* Subtract out existing available top space from MORECORE request. */
-+ asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE);
-+ /* Use mem here only if it did continuously extend old space */
-+ if (asize < HALF_MAX_SIZE_T &&
-+ (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) {
-+ tbase = br;
-+ tsize = asize;
-+ }
-+ }
-+
-+ if (tbase == CMFAIL) { /* Cope with partial failure */
-+ if (br != CMFAIL) { /* Try to use/extend the space we did get */
-+ if (asize < HALF_MAX_SIZE_T &&
-+ asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) {
-+ size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize);
-+ if (esize < HALF_MAX_SIZE_T) {
-+ char* end = (char*)CALL_MORECORE(esize);
-+ if (end != CMFAIL)
-+ asize += esize;
-+ else { /* Can't use; try to release */
-+ (void)CALL_MORECORE(-asize);
-+ br = CMFAIL;
-+ }
-+ }
-+ }
-+ }
-+ if (br != CMFAIL) { /* Use the space we did get */
-+ tbase = br;
-+ tsize = asize;
-+ }
-+ else
-+ disable_contiguous(m); /* Don't try contiguous path in the future */
-+ }
-+
-+ RELEASE_MORECORE_LOCK();
-+ }
-+
-+ if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */
-+ size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
-+ size_t rsize = granularity_align(req);
-+ if (rsize > nb) { /* Fail if wraps around zero */
-+ char* mp = (char*)(CALL_MMAP(rsize));
-+ if (mp != CMFAIL) {
-+ tbase = mp;
-+ tsize = rsize;
-+ mmap_flag = IS_MMAPPED_BIT;
-+ }
-+ }
-+ }
-+
-+ if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */
-+ size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE);
-+ if (asize < HALF_MAX_SIZE_T) {
-+ char* br = CMFAIL;
-+ char* end = CMFAIL;
-+ ACQUIRE_MORECORE_LOCK();
-+ br = (char*)(CALL_MORECORE(asize));
-+ end = (char*)(CALL_MORECORE(0));
-+ RELEASE_MORECORE_LOCK();
-+ if (br != CMFAIL && end != CMFAIL && br < end) {
-+ size_t ssize = end - br;
-+ if (ssize > nb + TOP_FOOT_SIZE) {
-+ tbase = br;
-+ tsize = ssize;
-+ }
-+ }
-+ }
-+ }
-+
-+ if (tbase != CMFAIL) {
-+
-+ if ((m->footprint += tsize) > m->max_footprint)
-+ m->max_footprint = m->footprint;
-+
-+ if (!is_initialized(m)) { /* first-time initialization */
-+ m->seg.base = m->least_addr = tbase;
-+ m->seg.size = tsize;
-+ (void)set_segment_flags(&m->seg, mmap_flag);
-+ m->magic = mparams.magic;
-+ init_bins(m);
-+ if (is_global(m))
-+ init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
-+ else {
-+ /* Offset top by embedded malloc_state */
-+ mchunkptr mn = next_chunk(mem2chunk(m));
-+ init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE);
-+ }
-+ }
-+
-+ else {
-+ /* Try to merge with an existing segment */
-+ msegmentptr sp = &m->seg;
-+ while (sp != 0 && tbase != sp->base + sp->size)
-+ sp = sp->next;
-+ if (sp != 0 &&
-+ !is_extern_segment(sp) &&
-+ check_segment_merge(sp, tbase, tsize) &&
-+ (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag &&
-+ segment_holds(sp, m->top)) { /* append */
-+ sp->size += tsize;
-+ init_top(m, m->top, m->topsize + tsize);
-+ }
-+ else {
-+ if (tbase < m->least_addr)
-+ m->least_addr = tbase;
-+ sp = &m->seg;
-+ while (sp != 0 && sp->base != tbase + tsize)
-+ sp = sp->next;
-+ if (sp != 0 &&
-+ !is_extern_segment(sp) &&
-+ check_segment_merge(sp, tbase, tsize) &&
-+ (get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag) {
-+ char* oldbase = sp->base;
-+ sp->base = tbase;
-+ sp->size += tsize;
-+ return prepend_alloc(m, tbase, oldbase, nb);
-+ }
-+ else
-+ add_segment(m, tbase, tsize, mmap_flag);
-+ }
-+ }
-+
-+ if (nb < m->topsize) { /* Allocate from new or extended top space */
-+ size_t rsize = m->topsize -= nb;
-+ mchunkptr p = m->top;
-+ mchunkptr r = m->top = chunk_plus_offset(p, nb);
-+ r->head = rsize | PINUSE_BIT;
-+ set_size_and_pinuse_of_inuse_chunk(m, p, nb);
-+ check_top_chunk(m, m->top);
-+ check_malloced_chunk(m, chunk2mem(p), nb);
-+ return chunk2mem(p);
-+ }
-+ }
-+
-+ MALLOC_FAILURE_ACTION;
-+ return 0;
-+}
-+
-+/* ----------------------- system deallocation -------------------------- */
-+
-+/* Unmap and unlink any mmapped segments that don't contain used chunks */
-+static size_t release_unused_segments(mstate m) {
-+ size_t released = 0;
-+ msegmentptr pred = &m->seg;
-+ msegmentptr sp = pred->next;
-+ while (sp != 0) {
-+ char* base = sp->base;
-+ size_t size = sp->size;
-+ msegmentptr next = sp->next;
-+ if (is_mmapped_segment(sp) && !is_extern_segment(sp)) {
-+ mchunkptr p = align_as_chunk(base);
-+ size_t psize = chunksize(p);
-+ /* Can unmap if first chunk holds entire segment and not pinned */
-+ if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) {
-+ tchunkptr tp = (tchunkptr)p;
-+ assert(segment_holds(sp, (char*)sp));
-+ if (p == m->dv) {
-+ m->dv = 0;
-+ m->dvsize = 0;
-+ }
-+ else {
-+ unlink_large_chunk(m, tp);
-+ }
-+ if (CALL_MUNMAP(base, size) == 0) {
-+ released += size;
-+ m->footprint -= size;
-+ /* unlink obsoleted record */
-+ sp = pred;
-+ sp->next = next;
-+ }
-+ else { /* back out if cannot unmap */
-+ insert_large_chunk(m, tp, psize);
-+ }
-+ }
-+ }
-+ pred = sp;
-+ sp = next;
-+ }
-+ return released;
-+}
-+
-+static int sys_trim(mstate m, size_t pad) {
-+ size_t released = 0;
-+ if (pad < MAX_REQUEST && is_initialized(m)) {
-+ pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
-+
-+ if (m->topsize > pad) {
-+ /* Shrink top space in granularity-size units, keeping at least one */
-+ size_t unit = mparams.granularity;
-+ size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
-+ SIZE_T_ONE) * unit;
-+ msegmentptr sp = segment_holding(m, (char*)m->top);
-+
-+ if (!is_extern_segment(sp)) {
-+ if (is_mmapped_segment(sp)) {
-+ if (HAVE_MMAP &&
-+ sp->size >= extra &&
-+ !has_segment_link(m, sp)) { /* can't shrink if pinned */
-+ size_t newsize = sp->size - extra;
-+ /* Prefer mremap, fall back to munmap */
-+ if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) ||
-+ (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
-+ released = extra;
-+ }
-+ }
-+ }
-+ else if (HAVE_MORECORE) {
-+ if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */
-+ extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit;
-+ ACQUIRE_MORECORE_LOCK();
-+ {
-+ /* Make sure end of memory is where we last set it. */
-+ char* old_br = (char*)(CALL_MORECORE(0));
-+ if (old_br == sp->base + sp->size) {
-+ char* rel_br = (char*)(CALL_MORECORE(-extra));
-+ char* new_br = (char*)(CALL_MORECORE(0));
-+ if (rel_br != CMFAIL && new_br < old_br)
-+ released = old_br - new_br;
-+ }
-+ }
-+ RELEASE_MORECORE_LOCK();
-+ }
-+ }
-+
-+ if (released != 0) {
-+ sp->size -= released;
-+ m->footprint -= released;
-+ init_top(m, m->top, m->topsize - released);
-+ check_top_chunk(m, m->top);
-+ }
-+ }
-+
-+ /* Unmap any unused mmapped segments */
-+ if (HAVE_MMAP)
-+ released += release_unused_segments(m);
-+
-+ /* On failure, disable autotrim to avoid repeated failed future calls */
-+ if (released == 0)
-+ m->trim_check = MAX_SIZE_T;
-+ }
-+
-+ return (released != 0)? 1 : 0;
-+}
-+
-+/* ---------------------------- malloc support --------------------------- */
-+
-+/* allocate a large request from the best fitting chunk in a treebin */
-+static void* tmalloc_large(mstate m, size_t nb) {
-+ tchunkptr v = 0;
-+ size_t rsize = -nb; /* Unsigned negation */
-+ tchunkptr t;
-+ bindex_t idx;
-+ compute_tree_index(nb, idx);
-+
-+ if ((t = *treebin_at(m, idx)) != 0) {
-+ /* Traverse tree for this bin looking for node with size == nb */
-+ size_t sizebits = nb << leftshift_for_tree_index(idx);
-+ tchunkptr rst = 0; /* The deepest untaken right subtree */
-+ for (;;) {
-+ tchunkptr rt;
-+ size_t trem = chunksize(t) - nb;
-+ if (trem < rsize) {
-+ v = t;
-+ if ((rsize = trem) == 0)
-+ break;
-+ }
-+ rt = t->child[1];
-+ t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
-+ if (rt != 0 && rt != t)
-+ rst = rt;
-+ if (t == 0) {
-+ t = rst; /* set t to least subtree holding sizes > nb */
-+ break;
-+ }
-+ sizebits <<= 1;
-+ }
-+ }
-+
-+ if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
-+ binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
-+ if (leftbits != 0) {
-+ bindex_t i;
-+ binmap_t leastbit = least_bit(leftbits);
-+ compute_bit2idx(leastbit, i);
-+ t = *treebin_at(m, i);
-+ }
-+ }
-+
-+ while (t != 0) { /* find smallest of tree or subtree */
-+ size_t trem = chunksize(t) - nb;
-+ if (trem < rsize) {
-+ rsize = trem;
-+ v = t;
-+ }
-+ t = leftmost_child(t);
-+ }
-+
-+ /* If dv is a better fit, return 0 so malloc will use it */
-+ if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
-+ if (RTCHECK(ok_address(m, v))) { /* split */
-+ mchunkptr r = chunk_plus_offset(v, nb);
-+ assert(chunksize(v) == rsize + nb);
-+ if (RTCHECK(ok_next(v, r))) {
-+ unlink_large_chunk(m, v);
-+ if (rsize < MIN_CHUNK_SIZE)
-+ set_inuse_and_pinuse(m, v, (rsize + nb));
-+ else {
-+ set_size_and_pinuse_of_inuse_chunk(m, v, nb);
-+ set_size_and_pinuse_of_free_chunk(r, rsize);
-+ insert_chunk(m, r, rsize);
-+ }
-+ return chunk2mem(v);
-+ }
-+ }
-+ CORRUPTION_ERROR_ACTION(m);
-+ }
-+ return 0;
-+}
-+
-+/* allocate a small request from the best fitting chunk in a treebin */
-+static void* tmalloc_small(mstate m, size_t nb) {
-+ tchunkptr t, v;
-+ size_t rsize;
-+ bindex_t i;
-+ binmap_t leastbit = least_bit(m->treemap);
-+ compute_bit2idx(leastbit, i);
-+
-+ v = t = *treebin_at(m, i);
-+ rsize = chunksize(t) - nb;
-+
-+ while ((t = leftmost_child(t)) != 0) {
-+ size_t trem = chunksize(t) - nb;
-+ if (trem < rsize) {
-+ rsize = trem;
-+ v = t;
-+ }
-+ }
-+
-+ if (RTCHECK(ok_address(m, v))) {
-+ mchunkptr r = chunk_plus_offset(v, nb);
-+ assert(chunksize(v) == rsize + nb);
-+ if (RTCHECK(ok_next(v, r))) {
-+ unlink_large_chunk(m, v);
-+ if (rsize < MIN_CHUNK_SIZE)
-+ set_inuse_and_pinuse(m, v, (rsize + nb));
-+ else {
-+ set_size_and_pinuse_of_inuse_chunk(m, v, nb);
-+ set_size_and_pinuse_of_free_chunk(r, rsize);
-+ replace_dv(m, r, rsize);
-+ }
-+ return chunk2mem(v);
-+ }
-+ }
-+
-+ CORRUPTION_ERROR_ACTION(m);
-+ return 0;
-+}
-+
-+/* --------------------------- realloc support --------------------------- */
-+
-+static void* internal_realloc(mstate m, void* oldmem, size_t bytes) {
-+ if (bytes >= MAX_REQUEST) {
-+ MALLOC_FAILURE_ACTION;
-+ return 0;
-+ }
-+ if (!PREACTION(m)) {
-+ mchunkptr oldp = mem2chunk(oldmem);
-+ size_t oldsize = chunksize(oldp);
-+ mchunkptr next = chunk_plus_offset(oldp, oldsize);
-+ mchunkptr newp = 0;
-+ void* extra = 0;
-+
-+ /* Try to either shrink or extend into top. Else malloc-copy-free */
-+
-+ if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) &&
-+ ok_next(oldp, next) && ok_pinuse(next))) {
-+ size_t nb = request2size(bytes);
-+ if (is_mmapped(oldp))
-+ newp = mmap_resize(m, oldp, nb);
-+ else if (oldsize >= nb) { /* already big enough */
-+ size_t rsize = oldsize - nb;
-+ newp = oldp;
-+ if (rsize >= MIN_CHUNK_SIZE) {
-+ mchunkptr remainder = chunk_plus_offset(newp, nb);
-+ set_inuse(m, newp, nb);
-+ set_inuse(m, remainder, rsize);
-+ extra = chunk2mem(remainder);
-+ }
-+ }
-+ else if (next == m->top && oldsize + m->topsize > nb) {
-+ /* Expand into top */
-+ size_t newsize = oldsize + m->topsize;
-+ size_t newtopsize = newsize - nb;
-+ mchunkptr newtop = chunk_plus_offset(oldp, nb);
-+ set_inuse(m, oldp, nb);
-+ newtop->head = newtopsize |PINUSE_BIT;
-+ m->top = newtop;
-+ m->topsize = newtopsize;
-+ newp = oldp;
-+ }
-+ }
-+ else {
-+ USAGE_ERROR_ACTION(m, oldmem);
-+ POSTACTION(m);
-+ return 0;
-+ }
-+
-+ POSTACTION(m);
-+
-+ if (newp != 0) {
-+ if (extra != 0) {
-+ internal_free(m, extra);
-+ }
-+ check_inuse_chunk(m, newp);
-+ return chunk2mem(newp);
-+ }
-+ else {
-+ void* newmem = internal_malloc(m, bytes);
-+ if (newmem != 0) {
-+ size_t oc = oldsize - overhead_for(oldp);
-+ memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
-+ internal_free(m, oldmem);
-+ }
-+ return newmem;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* --------------------------- memalign support -------------------------- */
-+
-+static void* internal_memalign(mstate m, size_t alignment, size_t bytes) {
-+ if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */
-+ return internal_malloc(m, bytes);
-+ if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */
-+ alignment = MIN_CHUNK_SIZE;
-+ if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */
-+ size_t a = MALLOC_ALIGNMENT << 1;
-+ while (a < alignment) a <<= 1;
-+ alignment = a;
-+ }
-+
-+ if (bytes >= MAX_REQUEST - alignment) {
-+ if (m != 0) { /* Test isn't needed but avoids compiler warning */
-+ MALLOC_FAILURE_ACTION;
-+ }
-+ }
-+ else {
-+ size_t nb = request2size(bytes);
-+ size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
-+ char* mem = (char*)internal_malloc(m, req);
-+ if (mem != 0) {
-+ void* leader = 0;
-+ void* trailer = 0;
-+ mchunkptr p = mem2chunk(mem);
-+
-+ if (PREACTION(m)) return 0;
-+ if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */
-+ /*
-+ Find an aligned spot inside chunk. Since we need to give
-+ back leading space in a chunk of at least MIN_CHUNK_SIZE, if
-+ the first calculation places us at a spot with less than
-+ MIN_CHUNK_SIZE leader, we can move to the next aligned spot.
-+ We've allocated enough total room so that this is always
-+ possible.
-+ */
-+ char* br = (char*)mem2chunk((size_t)(((size_t)(mem +
-+ alignment -
-+ SIZE_T_ONE)) &
-+ -alignment));
-+ char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)?
-+ br : br+alignment;
-+ mchunkptr newp = (mchunkptr)pos;
-+ size_t leadsize = pos - (char*)(p);
-+ size_t newsize = chunksize(p) - leadsize;
-+
-+ if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */
-+ newp->prev_foot = p->prev_foot + leadsize;
-+ newp->head = (newsize|CINUSE_BIT);
-+ }
-+ else { /* Otherwise, give back leader, use the rest */
-+ set_inuse(m, newp, newsize);
-+ set_inuse(m, p, leadsize);
-+ leader = chunk2mem(p);
-+ }
-+ p = newp;
-+ }
-+
-+ /* Give back spare room at the end */
-+ if (!is_mmapped(p)) {
-+ size_t size = chunksize(p);
-+ if (size > nb + MIN_CHUNK_SIZE) {
-+ size_t remainder_size = size - nb;
-+ mchunkptr remainder = chunk_plus_offset(p, nb);
-+ set_inuse(m, p, nb);
-+ set_inuse(m, remainder, remainder_size);
-+ trailer = chunk2mem(remainder);
-+ }
-+ }
-+
-+ assert (chunksize(p) >= nb);
-+ assert((((size_t)(chunk2mem(p))) % alignment) == 0);
-+ check_inuse_chunk(m, p);
-+ POSTACTION(m);
-+ if (leader != 0) {
-+ internal_free(m, leader);
-+ }
-+ if (trailer != 0) {
-+ internal_free(m, trailer);
-+ }
-+ return chunk2mem(p);
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* ------------------------ comalloc/coalloc support --------------------- */
-+
-+static void** ialloc(mstate m,
-+ size_t n_elements,
-+ size_t* sizes,
-+ int opts,
-+ void* chunks[]) {
-+ /*
-+ This provides common support for independent_X routines, handling
-+ all of the combinations that can result.
-+
-+ The opts arg has:
-+ bit 0 set if all elements are same size (using sizes[0])
-+ bit 1 set if elements should be zeroed
-+ */
-+
-+ size_t element_size; /* chunksize of each element, if all same */
-+ size_t contents_size; /* total size of elements */
-+ size_t array_size; /* request size of pointer array */
-+ void* mem; /* malloced aggregate space */
-+ mchunkptr p; /* corresponding chunk */
-+ size_t remainder_size; /* remaining bytes while splitting */
-+ void** marray; /* either "chunks" or malloced ptr array */
-+ mchunkptr array_chunk; /* chunk for malloced ptr array */
-+ flag_t was_enabled; /* to disable mmap */
-+ size_t size;
-+ size_t i;
-+
-+ /* compute array length, if needed */
-+ if (chunks != 0) {
-+ if (n_elements == 0)
-+ return chunks; /* nothing to do */
-+ marray = chunks;
-+ array_size = 0;
-+ }
-+ else {
-+ /* if empty req, must still return chunk representing empty array */
-+ if (n_elements == 0)
-+ return (void**)internal_malloc(m, 0);
-+ marray = 0;
-+ array_size = request2size(n_elements * (sizeof(void*)));
-+ }
-+
-+ /* compute total element size */
-+ if (opts & 0x1) { /* all-same-size */
-+ element_size = request2size(*sizes);
-+ contents_size = n_elements * element_size;
-+ }
-+ else { /* add up all the sizes */
-+ element_size = 0;
-+ contents_size = 0;
-+ for (i = 0; i != n_elements; ++i)
-+ contents_size += request2size(sizes[i]);
-+ }
-+
-+ size = contents_size + array_size;
-+
-+ /*
-+ Allocate the aggregate chunk. First disable direct-mmapping so
-+ malloc won't use it, since we would not be able to later
-+ free/realloc space internal to a segregated mmap region.
-+ */
-+ was_enabled = use_mmap(m);
-+ disable_mmap(m);
-+ mem = internal_malloc(m, size - CHUNK_OVERHEAD);
-+ if (was_enabled)
-+ enable_mmap(m);
-+ if (mem == 0)
-+ return 0;
-+
-+ if (PREACTION(m)) return 0;
-+ p = mem2chunk(mem);
-+ remainder_size = chunksize(p);
-+
-+ assert(!is_mmapped(p));
-+
-+ if (opts & 0x2) { /* optionally clear the elements */
-+ memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size);
-+ }
-+
-+ /* If not provided, allocate the pointer array as final part of chunk */
-+ if (marray == 0) {
-+ size_t array_chunk_size;
-+ array_chunk = chunk_plus_offset(p, contents_size);
-+ array_chunk_size = remainder_size - contents_size;
-+ marray = (void**) (chunk2mem(array_chunk));
-+ set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
-+ remainder_size = contents_size;
-+ }
-+
-+ /* split out elements */
-+ for (i = 0; ; ++i) {
-+ marray[i] = chunk2mem(p);
-+ if (i != n_elements-1) {
-+ if (element_size != 0)
-+ size = element_size;
-+ else
-+ size = request2size(sizes[i]);
-+ remainder_size -= size;
-+ set_size_and_pinuse_of_inuse_chunk(m, p, size);
-+ p = chunk_plus_offset(p, size);
-+ }
-+ else { /* the final element absorbs any overallocation slop */
-+ set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size);
-+ break;
-+ }
-+ }
-+
-+#if DEBUG
-+ if (marray != chunks) {
-+ /* final element must have exactly exhausted chunk */
-+ if (element_size != 0) {
-+ assert(remainder_size == element_size);
-+ }
-+ else {
-+ assert(remainder_size == request2size(sizes[i]));
-+ }
-+ check_inuse_chunk(m, mem2chunk(marray));
-+ }
-+ for (i = 0; i != n_elements; ++i)
-+ check_inuse_chunk(m, mem2chunk(marray[i]));
-+
-+#endif /* DEBUG */
-+
-+ POSTACTION(m);
-+ return marray;
-+}
-+
-+
-+/* -------------------------- public routines ---------------------------- */
-+
-+#if !ONLY_MSPACES
-+
-+void* dlmalloc(size_t bytes) {
-+ /*
-+ Basic algorithm:
-+ If a small request (< 256 bytes minus per-chunk overhead):
-+ 1. If one exists, use a remainderless chunk in associated smallbin.
-+ (Remainderless means that there are too few excess bytes to
-+ represent as a chunk.)
-+ 2. If it is big enough, use the dv chunk, which is normally the
-+ chunk adjacent to the one used for the most recent small request.
-+ 3. If one exists, split the smallest available chunk in a bin,
-+ saving remainder in dv.
-+ 4. If it is big enough, use the top chunk.
-+ 5. If available, get memory from system and use it
-+ Otherwise, for a large request:
-+ 1. Find the smallest available binned chunk that fits, and use it
-+ if it is better fitting than dv chunk, splitting if necessary.
-+ 2. If better fitting than any binned chunk, use the dv chunk.
-+ 3. If it is big enough, use the top chunk.
-+ 4. If request size >= mmap threshold, try to directly mmap this chunk.
-+ 5. If available, get memory from system and use it
-+
-+ The ugly goto's here ensure that postaction occurs along all paths.
-+ */
-+
-+ if (!PREACTION(gm)) {
-+ void* mem;
-+ size_t nb;
-+ if (bytes <= MAX_SMALL_REQUEST) {
-+ bindex_t idx;
-+ binmap_t smallbits;
-+ nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
-+ idx = small_index(nb);
-+ smallbits = gm->smallmap >> idx;
-+
-+ if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
-+ mchunkptr b, p;
-+ idx += ~smallbits & 1; /* Uses next bin if idx empty */
-+ b = smallbin_at(gm, idx);
-+ p = b->fd;
-+ assert(chunksize(p) == small_index2size(idx));
-+ unlink_first_small_chunk(gm, b, p, idx);
-+ set_inuse_and_pinuse(gm, p, small_index2size(idx));
-+ mem = chunk2mem(p);
-+ check_malloced_chunk(gm, mem, nb);
-+ goto postaction;
-+ }
-+
-+ else if (nb > gm->dvsize) {
-+ if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
-+ mchunkptr b, p, r;
-+ size_t rsize;
-+ bindex_t i;
-+ binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
-+ binmap_t leastbit = least_bit(leftbits);
-+ compute_bit2idx(leastbit, i);
-+ b = smallbin_at(gm, i);
-+ p = b->fd;
-+ assert(chunksize(p) == small_index2size(i));
-+ unlink_first_small_chunk(gm, b, p, i);
-+ rsize = small_index2size(i) - nb;
-+ /* Fit here cannot be remainderless if 4byte sizes */
-+ if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
-+ set_inuse_and_pinuse(gm, p, small_index2size(i));
-+ else {
-+ set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
-+ r = chunk_plus_offset(p, nb);
-+ set_size_and_pinuse_of_free_chunk(r, rsize);
-+ replace_dv(gm, r, rsize);
-+ }
-+ mem = chunk2mem(p);
-+ check_malloced_chunk(gm, mem, nb);
-+ goto postaction;
-+ }
-+
-+ else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) {
-+ check_malloced_chunk(gm, mem, nb);
-+ goto postaction;
-+ }
-+ }
-+ }
-+ else if (bytes >= MAX_REQUEST)
-+ nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
-+ else {
-+ nb = pad_request(bytes);
-+ if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) {
-+ check_malloced_chunk(gm, mem, nb);
-+ goto postaction;
-+ }
-+ }
-+
-+ if (nb <= gm->dvsize) {
-+ size_t rsize = gm->dvsize - nb;
-+ mchunkptr p = gm->dv;
-+ if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
-+ mchunkptr r = gm->dv = chunk_plus_offset(p, nb);
-+ gm->dvsize = rsize;
-+ set_size_and_pinuse_of_free_chunk(r, rsize);
-+ set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
-+ }
-+ else { /* exhaust dv */
-+ size_t dvs = gm->dvsize;
-+ gm->dvsize = 0;
-+ gm->dv = 0;
-+ set_inuse_and_pinuse(gm, p, dvs);
-+ }
-+ mem = chunk2mem(p);
-+ check_malloced_chunk(gm, mem, nb);
-+ goto postaction;
-+ }
-+
-+ else if (nb < gm->topsize) { /* Split top */
-+ size_t rsize = gm->topsize -= nb;
-+ mchunkptr p = gm->top;
-+ mchunkptr r = gm->top = chunk_plus_offset(p, nb);
-+ r->head = rsize | PINUSE_BIT;
-+ set_size_and_pinuse_of_inuse_chunk(gm, p, nb);
-+ mem = chunk2mem(p);
-+ check_top_chunk(gm, gm->top);
-+ check_malloced_chunk(gm, mem, nb);
-+ goto postaction;
-+ }
-+
-+ mem = sys_alloc(gm, nb);
-+
-+ postaction:
-+ POSTACTION(gm);
-+ return mem;
-+ }
-+
-+ return 0;
-+}
-+
-+void dlfree(void* mem) {
-+ /*
-+ Consolidate freed chunks with preceding or succeeding bordering
-+ free chunks, if they exist, and then place in a bin. Intermixed
-+ with special cases for top, dv, mmapped chunks, and usage errors.
-+ */
-+
-+ if (mem != 0) {
-+ mchunkptr p = mem2chunk(mem);
-+#if FOOTERS
-+ mstate fm = get_mstate_for(p);
-+ if (!ok_magic(fm)) {
-+ USAGE_ERROR_ACTION(fm, p);
-+ return;
-+ }
-+#else /* FOOTERS */
-+#define fm gm
-+#endif /* FOOTERS */
-+ if (!PREACTION(fm)) {
-+ check_inuse_chunk(fm, p);
-+ if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
-+ size_t psize = chunksize(p);
-+ mchunkptr next = chunk_plus_offset(p, psize);
-+ if (!pinuse(p)) {
-+ size_t prevsize = p->prev_foot;
-+ if ((prevsize & IS_MMAPPED_BIT) != 0) {
-+ prevsize &= ~IS_MMAPPED_BIT;
-+ psize += prevsize + MMAP_FOOT_PAD;
-+ if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
-+ fm->footprint -= psize;
-+ goto postaction;
-+ }
-+ else {
-+ mchunkptr prev = chunk_minus_offset(p, prevsize);
-+ psize += prevsize;
-+ p = prev;
-+ if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
-+ if (p != fm->dv) {
-+ unlink_chunk(fm, p, prevsize);
-+ }
-+ else if ((next->head & INUSE_BITS) == INUSE_BITS) {
-+ fm->dvsize = psize;
-+ set_free_with_pinuse(p, psize, next);
-+ goto postaction;
-+ }
-+ }
-+ else
-+ goto erroraction;
-+ }
-+ }
-+
-+ if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
-+ if (!cinuse(next)) { /* consolidate forward */
-+ if (next == fm->top) {
-+ size_t tsize = fm->topsize += psize;
-+ fm->top = p;
-+ p->head = tsize | PINUSE_BIT;
-+ if (p == fm->dv) {
-+ fm->dv = 0;
-+ fm->dvsize = 0;
-+ }
-+ if (should_trim(fm, tsize))
-+ sys_trim(fm, 0);
-+ goto postaction;
-+ }
-+ else if (next == fm->dv) {
-+ size_t dsize = fm->dvsize += psize;
-+ fm->dv = p;
-+ set_size_and_pinuse_of_free_chunk(p, dsize);
-+ goto postaction;
-+ }
-+ else {
-+ size_t nsize = chunksize(next);
-+ psize += nsize;
-+ unlink_chunk(fm, next, nsize);
-+ set_size_and_pinuse_of_free_chunk(p, psize);
-+ if (p == fm->dv) {
-+ fm->dvsize = psize;
-+ goto postaction;
-+ }
-+ }
-+ }
-+ else
-+ set_free_with_pinuse(p, psize, next);
-+ insert_chunk(fm, p, psize);
-+ check_free_chunk(fm, p);
-+ goto postaction;
-+ }
-+ }
-+ erroraction:
-+ USAGE_ERROR_ACTION(fm, p);
-+ postaction:
-+ POSTACTION(fm);
-+ }
-+ }
-+#if !FOOTERS
-+#undef fm
-+#endif /* FOOTERS */
-+}
-+
-+void* dlcalloc(size_t n_elements, size_t elem_size) {
-+ void* mem;
-+ size_t req = 0;
-+ if (n_elements != 0) {
-+ req = n_elements * elem_size;
-+ if (((n_elements | elem_size) & ~(size_t)0xffff) &&
-+ (req / n_elements != elem_size))
-+ req = MAX_SIZE_T; /* force downstream failure on overflow */
-+ }
-+ mem = dlmalloc(req);
-+ if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
-+ memset(mem, 0, req);
-+ return mem;
-+}
-+
-+void* dlrealloc(void* oldmem, size_t bytes) {
-+ if (oldmem == 0)
-+ return dlmalloc(bytes);
-+#ifdef REALLOC_ZERO_BYTES_FREES
-+ if (bytes == 0) {
-+ dlfree(oldmem);
-+ return 0;
-+ }
-+#endif /* REALLOC_ZERO_BYTES_FREES */
-+ else {
-+#if ! FOOTERS
-+ mstate m = gm;
-+#else /* FOOTERS */
-+ mstate m = get_mstate_for(mem2chunk(oldmem));
-+ if (!ok_magic(m)) {
-+ USAGE_ERROR_ACTION(m, oldmem);
-+ return 0;
-+ }
-+#endif /* FOOTERS */
-+ return internal_realloc(m, oldmem, bytes);
-+ }
-+}
-+
-+void* dlmemalign(size_t alignment, size_t bytes) {
-+ return internal_memalign(gm, alignment, bytes);
-+}
-+
-+void** dlindependent_calloc(size_t n_elements, size_t elem_size,
-+ void* chunks[]) {
-+ size_t sz = elem_size; /* serves as 1-element array */
-+ return ialloc(gm, n_elements, &sz, 3, chunks);
-+}
-+
-+void** dlindependent_comalloc(size_t n_elements, size_t sizes[],
-+ void* chunks[]) {
-+ return ialloc(gm, n_elements, sizes, 0, chunks);
-+}
-+
-+void* dlvalloc(size_t bytes) {
-+ size_t pagesz;
-+ init_mparams();
-+ pagesz = mparams.page_size;
-+ return dlmemalign(pagesz, bytes);
-+}
-+
-+void* dlpvalloc(size_t bytes) {
-+ size_t pagesz;
-+ init_mparams();
-+ pagesz = mparams.page_size;
-+ return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE));
-+}
-+
-+int dlmalloc_trim(size_t pad) {
-+ int result = 0;
-+ if (!PREACTION(gm)) {
-+ result = sys_trim(gm, pad);
-+ POSTACTION(gm);
-+ }
-+ return result;
-+}
-+
-+size_t dlmalloc_footprint(void) {
-+ return gm->footprint;
-+}
-+
-+size_t dlmalloc_max_footprint(void) {
-+ return gm->max_footprint;
-+}
-+
-+#if !NO_MALLINFO
-+struct mallinfo dlmallinfo(void) {
-+ return internal_mallinfo(gm);
-+}
-+#endif /* NO_MALLINFO */
-+
-+void dlmalloc_stats() {
-+ internal_malloc_stats(gm);
-+}
-+
-+size_t dlmalloc_usable_size(void* mem) {
-+ if (mem != 0) {
-+ mchunkptr p = mem2chunk(mem);
-+ if (cinuse(p))
-+ return chunksize(p) - overhead_for(p);
-+ }
-+ return 0;
-+}
-+
-+int dlmallopt(int param_number, int value) {
-+ return change_mparam(param_number, value);
-+}
-+
-+#endif /* !ONLY_MSPACES */
-+
-+/* ----------------------------- user mspaces ---------------------------- */
-+
-+#if MSPACES
-+
-+static mstate init_user_mstate(char* tbase, size_t tsize) {
-+ size_t msize = pad_request(sizeof(struct malloc_state));
-+ mchunkptr mn;
-+ mchunkptr msp = align_as_chunk(tbase);
-+ mstate m = (mstate)(chunk2mem(msp));
-+ memset(m, 0, msize);
-+ INITIAL_LOCK(&m->mutex);
-+ msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
-+ m->seg.base = m->least_addr = tbase;
-+ m->seg.size = m->footprint = m->max_footprint = tsize;
-+ m->magic = mparams.magic;
-+ m->mflags = mparams.default_mflags;
-+ disable_contiguous(m);
-+ init_bins(m);
-+ mn = next_chunk(mem2chunk(m));
-+ init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE);
-+ check_top_chunk(m, m->top);
-+ return m;
-+}
-+
-+mspace create_mspace(size_t capacity, int locked) {
-+ mstate m = 0;
-+ size_t msize = pad_request(sizeof(struct malloc_state));
-+ init_mparams(); /* Ensure pagesize etc initialized */
-+
-+ if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
-+ size_t rs = ((capacity == 0)? mparams.granularity :
-+ (capacity + TOP_FOOT_SIZE + msize));
-+ size_t tsize = granularity_align(rs);
-+ char* tbase = (char*)(CALL_MMAP(tsize));
-+ if (tbase != CMFAIL) {
-+ m = init_user_mstate(tbase, tsize);
-+ set_segment_flags(&m->seg, IS_MMAPPED_BIT);
-+ set_lock(m, locked);
-+ }
-+ }
-+ return (mspace)m;
-+}
-+
-+mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
-+ mstate m = 0;
-+ size_t msize = pad_request(sizeof(struct malloc_state));
-+ init_mparams(); /* Ensure pagesize etc initialized */
-+
-+ if (capacity > msize + TOP_FOOT_SIZE &&
-+ capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
-+ m = init_user_mstate((char*)base, capacity);
-+ set_segment_flags(&m->seg, EXTERN_BIT);
-+ set_lock(m, locked);
-+ }
-+ return (mspace)m;
-+}
-+
-+size_t destroy_mspace(mspace msp) {
-+ size_t freed = 0;
-+ mstate ms = (mstate)msp;
-+ if (ok_magic(ms)) {
-+ msegmentptr sp = &ms->seg;
-+ while (sp != 0) {
-+ char* base = sp->base;
-+ size_t size = sp->size;
-+ flag_t flag = get_segment_flags(sp);
-+ sp = sp->next;
-+ if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
-+ CALL_MUNMAP(base, size) == 0)
-+ freed += size;
-+ }
-+ }
-+ else {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ }
-+ return freed;
-+}
-+
-+/*
-+ mspace versions of routines are near-clones of the global
-+ versions. This is not so nice but better than the alternatives.
-+*/
-+
-+
-+void* mspace_malloc(mspace msp, size_t bytes) {
-+ mstate ms = (mstate)msp;
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return 0;
-+ }
-+ if (!PREACTION(ms)) {
-+ void* mem;
-+ size_t nb;
-+ if (bytes <= MAX_SMALL_REQUEST) {
-+ bindex_t idx;
-+ binmap_t smallbits;
-+ nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes);
-+ idx = small_index(nb);
-+ smallbits = ms->smallmap >> idx;
-+
-+ if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
-+ mchunkptr b, p;
-+ idx += ~smallbits & 1; /* Uses next bin if idx empty */
-+ b = smallbin_at(ms, idx);
-+ p = b->fd;
-+ assert(chunksize(p) == small_index2size(idx));
-+ unlink_first_small_chunk(ms, b, p, idx);
-+ set_inuse_and_pinuse(ms, p, small_index2size(idx));
-+ mem = chunk2mem(p);
-+ check_malloced_chunk(ms, mem, nb);
-+ goto postaction;
-+ }
-+
-+ else if (nb > ms->dvsize) {
-+ if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
-+ mchunkptr b, p, r;
-+ size_t rsize;
-+ bindex_t i;
-+ binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
-+ binmap_t leastbit = least_bit(leftbits);
-+ compute_bit2idx(leastbit, i);
-+ b = smallbin_at(ms, i);
-+ p = b->fd;
-+ assert(chunksize(p) == small_index2size(i));
-+ unlink_first_small_chunk(ms, b, p, i);
-+ rsize = small_index2size(i) - nb;
-+ /* Fit here cannot be remainderless if 4byte sizes */
-+ if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
-+ set_inuse_and_pinuse(ms, p, small_index2size(i));
-+ else {
-+ set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
-+ r = chunk_plus_offset(p, nb);
-+ set_size_and_pinuse_of_free_chunk(r, rsize);
-+ replace_dv(ms, r, rsize);
-+ }
-+ mem = chunk2mem(p);
-+ check_malloced_chunk(ms, mem, nb);
-+ goto postaction;
-+ }
-+
-+ else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
-+ check_malloced_chunk(ms, mem, nb);
-+ goto postaction;
-+ }
-+ }
-+ }
-+ else if (bytes >= MAX_REQUEST)
-+ nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
-+ else {
-+ nb = pad_request(bytes);
-+ if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
-+ check_malloced_chunk(ms, mem, nb);
-+ goto postaction;
-+ }
-+ }
-+
-+ if (nb <= ms->dvsize) {
-+ size_t rsize = ms->dvsize - nb;
-+ mchunkptr p = ms->dv;
-+ if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
-+ mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
-+ ms->dvsize = rsize;
-+ set_size_and_pinuse_of_free_chunk(r, rsize);
-+ set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
-+ }
-+ else { /* exhaust dv */
-+ size_t dvs = ms->dvsize;
-+ ms->dvsize = 0;
-+ ms->dv = 0;
-+ set_inuse_and_pinuse(ms, p, dvs);
-+ }
-+ mem = chunk2mem(p);
-+ check_malloced_chunk(ms, mem, nb);
-+ goto postaction;
-+ }
-+
-+ else if (nb < ms->topsize) { /* Split top */
-+ size_t rsize = ms->topsize -= nb;
-+ mchunkptr p = ms->top;
-+ mchunkptr r = ms->top = chunk_plus_offset(p, nb);
-+ r->head = rsize | PINUSE_BIT;
-+ set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
-+ mem = chunk2mem(p);
-+ check_top_chunk(ms, ms->top);
-+ check_malloced_chunk(ms, mem, nb);
-+ goto postaction;
-+ }
-+
-+ mem = sys_alloc(ms, nb);
-+
-+ postaction:
-+ POSTACTION(ms);
-+ return mem;
-+ }
-+
-+ return 0;
-+}
-+
-+void mspace_free(mspace msp, void* mem) {
-+ if (mem != 0) {
-+ mchunkptr p = mem2chunk(mem);
-+#if FOOTERS
-+ mstate fm = get_mstate_for(p);
-+#else /* FOOTERS */
-+ mstate fm = (mstate)msp;
-+#endif /* FOOTERS */
-+ if (!ok_magic(fm)) {
-+ USAGE_ERROR_ACTION(fm, p);
-+ return;
-+ }
-+ if (!PREACTION(fm)) {
-+ check_inuse_chunk(fm, p);
-+ if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) {
-+ size_t psize = chunksize(p);
-+ mchunkptr next = chunk_plus_offset(p, psize);
-+ if (!pinuse(p)) {
-+ size_t prevsize = p->prev_foot;
-+ if ((prevsize & IS_MMAPPED_BIT) != 0) {
-+ prevsize &= ~IS_MMAPPED_BIT;
-+ psize += prevsize + MMAP_FOOT_PAD;
-+ if (CALL_MUNMAP((char*)p - prevsize, psize) == 0)
-+ fm->footprint -= psize;
-+ goto postaction;
-+ }
-+ else {
-+ mchunkptr prev = chunk_minus_offset(p, prevsize);
-+ psize += prevsize;
-+ p = prev;
-+ if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */
-+ if (p != fm->dv) {
-+ unlink_chunk(fm, p, prevsize);
-+ }
-+ else if ((next->head & INUSE_BITS) == INUSE_BITS) {
-+ fm->dvsize = psize;
-+ set_free_with_pinuse(p, psize, next);
-+ goto postaction;
-+ }
-+ }
-+ else
-+ goto erroraction;
-+ }
-+ }
-+
-+ if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) {
-+ if (!cinuse(next)) { /* consolidate forward */
-+ if (next == fm->top) {
-+ size_t tsize = fm->topsize += psize;
-+ fm->top = p;
-+ p->head = tsize | PINUSE_BIT;
-+ if (p == fm->dv) {
-+ fm->dv = 0;
-+ fm->dvsize = 0;
-+ }
-+ if (should_trim(fm, tsize))
-+ sys_trim(fm, 0);
-+ goto postaction;
-+ }
-+ else if (next == fm->dv) {
-+ size_t dsize = fm->dvsize += psize;
-+ fm->dv = p;
-+ set_size_and_pinuse_of_free_chunk(p, dsize);
-+ goto postaction;
-+ }
-+ else {
-+ size_t nsize = chunksize(next);
-+ psize += nsize;
-+ unlink_chunk(fm, next, nsize);
-+ set_size_and_pinuse_of_free_chunk(p, psize);
-+ if (p == fm->dv) {
-+ fm->dvsize = psize;
-+ goto postaction;
-+ }
-+ }
-+ }
-+ else
-+ set_free_with_pinuse(p, psize, next);
-+ insert_chunk(fm, p, psize);
-+ check_free_chunk(fm, p);
-+ goto postaction;
-+ }
-+ }
-+ erroraction:
-+ USAGE_ERROR_ACTION(fm, p);
-+ postaction:
-+ POSTACTION(fm);
-+ }
-+ }
-+}
-+
-+void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
-+ void* mem;
-+ size_t req = 0;
-+ mstate ms = (mstate)msp;
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return 0;
-+ }
-+ if (n_elements != 0) {
-+ req = n_elements * elem_size;
-+ if (((n_elements | elem_size) & ~(size_t)0xffff) &&
-+ (req / n_elements != elem_size))
-+ req = MAX_SIZE_T; /* force downstream failure on overflow */
-+ }
-+ mem = internal_malloc(ms, req);
-+ if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
-+ memset(mem, 0, req);
-+ return mem;
-+}
-+
-+void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
-+ if (oldmem == 0)
-+ return mspace_malloc(msp, bytes);
-+#ifdef REALLOC_ZERO_BYTES_FREES
-+ if (bytes == 0) {
-+ mspace_free(msp, oldmem);
-+ return 0;
-+ }
-+#endif /* REALLOC_ZERO_BYTES_FREES */
-+ else {
-+#if FOOTERS
-+ mchunkptr p = mem2chunk(oldmem);
-+ mstate ms = get_mstate_for(p);
-+#else /* FOOTERS */
-+ mstate ms = (mstate)msp;
-+#endif /* FOOTERS */
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return 0;
-+ }
-+ return internal_realloc(ms, oldmem, bytes);
-+ }
-+}
-+
-+void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
-+ mstate ms = (mstate)msp;
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return 0;
-+ }
-+ return internal_memalign(ms, alignment, bytes);
-+}
-+
-+void** mspace_independent_calloc(mspace msp, size_t n_elements,
-+ size_t elem_size, void* chunks[]) {
-+ size_t sz = elem_size; /* serves as 1-element array */
-+ mstate ms = (mstate)msp;
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return 0;
-+ }
-+ return ialloc(ms, n_elements, &sz, 3, chunks);
-+}
-+
-+void** mspace_independent_comalloc(mspace msp, size_t n_elements,
-+ size_t sizes[], void* chunks[]) {
-+ mstate ms = (mstate)msp;
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return 0;
-+ }
-+ return ialloc(ms, n_elements, sizes, 0, chunks);
-+}
-+
-+int mspace_trim(mspace msp, size_t pad) {
-+ int result = 0;
-+ mstate ms = (mstate)msp;
-+ if (ok_magic(ms)) {
-+ if (!PREACTION(ms)) {
-+ result = sys_trim(ms, pad);
-+ POSTACTION(ms);
-+ }
-+ }
-+ else {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ }
-+ return result;
-+}
-+
-+void mspace_malloc_stats(mspace msp) {
-+ mstate ms = (mstate)msp;
-+ if (ok_magic(ms)) {
-+ internal_malloc_stats(ms);
-+ }
-+ else {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ }
-+}
-+
-+size_t mspace_footprint(mspace msp) {
-+ size_t result;
-+ mstate ms = (mstate)msp;
-+ if (ok_magic(ms)) {
-+ result = ms->footprint;
-+ }
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return result;
-+}
-+
-+
-+size_t mspace_max_footprint(mspace msp) {
-+ size_t result;
-+ mstate ms = (mstate)msp;
-+ if (ok_magic(ms)) {
-+ result = ms->max_footprint;
-+ }
-+ USAGE_ERROR_ACTION(ms,ms);
-+ return result;
-+}
-+
-+
-+#if !NO_MALLINFO
-+struct mallinfo mspace_mallinfo(mspace msp) {
-+ mstate ms = (mstate)msp;
-+ if (!ok_magic(ms)) {
-+ USAGE_ERROR_ACTION(ms,ms);
-+ }
-+ return internal_mallinfo(ms);
-+}
-+#endif /* NO_MALLINFO */
-+
-+int mspace_mallopt(int param_number, int value) {
-+ return change_mparam(param_number, value);
-+}
-+
-+#endif /* MSPACES */
-+
-+/* -------------------- Alternative MORECORE functions ------------------- */
-+
-+/*
-+ Guidelines for creating a custom version of MORECORE:
-+
-+ * For best performance, MORECORE should allocate in multiples of pagesize.
-+ * MORECORE may allocate more memory than requested. (Or even less,
-+ but this will usually result in a malloc failure.)
-+ * MORECORE must not allocate memory when given argument zero, but
-+ instead return one past the end address of memory from previous
-+ nonzero call.
-+ * For best performance, consecutive calls to MORECORE with positive
-+ arguments should return increasing addresses, indicating that
-+ space has been contiguously extended.
-+ * Even though consecutive calls to MORECORE need not return contiguous
-+ addresses, it must be OK for malloc'ed chunks to span multiple
-+ regions in those cases where they do happen to be contiguous.
-+ * MORECORE need not handle negative arguments -- it may instead
-+ just return MFAIL when given negative arguments.
-+ Negative arguments are always multiples of pagesize. MORECORE
-+ must not misinterpret negative args as large positive unsigned
-+ args. You can suppress all such calls from even occurring by defining
-+ MORECORE_CANNOT_TRIM,
-+
-+ As an example alternative MORECORE, here is a custom allocator
-+ kindly contributed for pre-OSX macOS. It uses virtually but not
-+ necessarily physically contiguous non-paged memory (locked in,
-+ present and won't get swapped out). You can use it by uncommenting
-+ this section, adding some #includes, and setting up the appropriate
-+ defines above:
-+
-+ #define MORECORE osMoreCore
-+
-+ There is also a shutdown routine that should somehow be called for
-+ cleanup upon program exit.
-+
-+ #define MAX_POOL_ENTRIES 100
-+ #define MINIMUM_MORECORE_SIZE (64 * 1024U)
-+ static int next_os_pool;
-+ void *our_os_pools[MAX_POOL_ENTRIES];
-+
-+ void *osMoreCore(int size)
-+ {
-+ void *ptr = 0;
-+ static void *sbrk_top = 0;
-+
-+ if (size > 0)
-+ {
-+ if (size < MINIMUM_MORECORE_SIZE)
-+ size = MINIMUM_MORECORE_SIZE;
-+ if (CurrentExecutionLevel() == kTaskLevel)
-+ ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
-+ if (ptr == 0)
-+ {
-+ return (void *) MFAIL;
-+ }
-+ // save ptrs so they can be freed during cleanup
-+ our_os_pools[next_os_pool] = ptr;
-+ next_os_pool++;
-+ ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
-+ sbrk_top = (char *) ptr + size;
-+ return ptr;
-+ }
-+ else if (size < 0)
-+ {
-+ // we don't currently support shrink behavior
-+ return (void *) MFAIL;
-+ }
-+ else
-+ {
-+ return sbrk_top;
-+ }
-+ }
-+
-+ // cleanup any allocated memory pools
-+ // called as last thing before shutting down driver
-+
-+ void osCleanupMem(void)
-+ {
-+ void **ptr;
-+
-+ for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
-+ if (*ptr)
-+ {
-+ PoolDeallocate(*ptr);
-+ *ptr = 0;
-+ }
-+ }
-+
-+*/
-+
-+
-+/* -----------------------------------------------------------------------
-+History:
-+ V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee)
-+ * Add max_footprint functions
-+ * Ensure all appropriate literals are size_t
-+ * Fix conditional compilation problem for some #define settings
-+ * Avoid concatenating segments with the one provided
-+ in create_mspace_with_base
-+ * Rename some variables to avoid compiler shadowing warnings
-+ * Use explicit lock initialization.
-+ * Better handling of sbrk interference.
-+ * Simplify and fix segment insertion, trimming and mspace_destroy
-+ * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
-+ * Thanks especially to Dennis Flanagan for help on these.
-+
-+ V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee)
-+ * Fix memalign brace error.
-+
-+ V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee)
-+ * Fix improper #endif nesting in C++
-+ * Add explicit casts needed for C++
-+
-+ V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee)
-+ * Use trees for large bins
-+ * Support mspaces
-+ * Use segments to unify sbrk-based and mmap-based system allocation,
-+ removing need for emulation on most platforms without sbrk.
-+ * Default safety checks
-+ * Optional footer checks. Thanks to William Robertson for the idea.
-+ * Internal code refactoring
-+ * Incorporate suggestions and platform-specific changes.
-+ Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
-+ Aaron Bachmann, Emery Berger, and others.
-+ * Speed up non-fastbin processing enough to remove fastbins.
-+ * Remove useless cfree() to avoid conflicts with other apps.
-+ * Remove internal memcpy, memset. Compilers handle builtins better.
-+ * Remove some options that no one ever used and rename others.
-+
-+ V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
-+ * Fix malloc_state bitmap array misdeclaration
-+
-+ V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee)
-+ * Allow tuning of FIRST_SORTED_BIN_SIZE
-+ * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
-+ * Better detection and support for non-contiguousness of MORECORE.
-+ Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
-+ * Bypass most of malloc if no frees. Thanks To Emery Berger.
-+ * Fix freeing of old top non-contiguous chunk im sysmalloc.
-+ * Raised default trim and map thresholds to 256K.
-+ * Fix mmap-related #defines. Thanks to Lubos Lunak.
-+ * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
-+ * Branch-free bin calculation
-+ * Default trim and mmap thresholds now 256K.
-+
-+ V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee)
-+ * Introduce independent_comalloc and independent_calloc.
-+ Thanks to Michael Pachos for motivation and help.
-+ * Make optional .h file available
-+ * Allow > 2GB requests on 32bit systems.
-+ * new WIN32 sbrk, mmap, munmap, lock code from .
-+ Thanks also to Andreas Mueller ,
-+ and Anonymous.
-+ * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
-+ helping test this.)
-+ * memalign: check alignment arg
-+ * realloc: don't try to shift chunks backwards, since this
-+ leads to more fragmentation in some programs and doesn't
-+ seem to help in any others.
-+ * Collect all cases in malloc requiring system memory into sysmalloc
-+ * Use mmap as backup to sbrk
-+ * Place all internal state in malloc_state
-+ * Introduce fastbins (although similar to 2.5.1)
-+ * Many minor tunings and cosmetic improvements
-+ * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
-+ * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
-+ Thanks to Tony E. Bennett and others.
-+ * Include errno.h to support default failure action.
-+
-+ V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
-+ * return null for negative arguments
-+ * Added Several WIN32 cleanups from Martin C. Fong
-+ * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
-+ (e.g. WIN32 platforms)
-+ * Cleanup header file inclusion for WIN32 platforms
-+ * Cleanup code to avoid Microsoft Visual C++ compiler complaints
-+ * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
-+ memory allocation routines
-+ * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
-+ * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
-+ usage of 'assert' in non-WIN32 code
-+ * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
-+ avoid infinite loop
-+ * Always call 'fREe()' rather than 'free()'
-+
-+ V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
-+ * Fixed ordering problem with boundary-stamping
-+
-+ V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
-+ * Added pvalloc, as recommended by H.J. Liu
-+ * Added 64bit pointer support mainly from Wolfram Gloger
-+ * Added anonymously donated WIN32 sbrk emulation
-+ * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
-+ * malloc_extend_top: fix mask error that caused wastage after
-+ foreign sbrks
-+ * Add linux mremap support code from HJ Liu
-+
-+ V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
-+ * Integrated most documentation with the code.
-+ * Add support for mmap, with help from
-+ Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
-+ * Use last_remainder in more cases.
-+ * Pack bins using idea from colin@nyx10.cs.du.edu
-+ * Use ordered bins instead of best-fit threshold
-+ * Eliminate block-local decls to simplify tracing and debugging.
-+ * Support another case of realloc via move into top
-+ * Fix error occurring when initial sbrk_base not word-aligned.
-+ * Rely on page size for units instead of SBRK_UNIT to
-+ avoid surprises about sbrk alignment conventions.
-+ * Add mallinfo, mallopt. Thanks to Raymond Nijssen
-+ (raymond@es.ele.tue.nl) for the suggestion.
-+ * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
-+ * More precautions for cases where other routines call sbrk,
-+ courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
-+ * Added macros etc., allowing use in linux libc from
-+ H.J. Lu (hjl@gnu.ai.mit.edu)
-+ * Inverted this history list
-+
-+ V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
-+ * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
-+ * Removed all preallocation code since under current scheme
-+ the work required to undo bad preallocations exceeds
-+ the work saved in good cases for most test programs.
-+ * No longer use return list or unconsolidated bins since
-+ no scheme using them consistently outperforms those that don't
-+ given above changes.
-+ * Use best fit for very large chunks to prevent some worst-cases.
-+ * Added some support for debugging
-+
-+ V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
-+ * Removed footers when chunks are in use. Thanks to
-+ Paul Wilson (wilson@cs.texas.edu) for the suggestion.
-+
-+ V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
-+ * Added malloc_trim, with help from Wolfram Gloger
-+ (wmglo@Dent.MED.Uni-Muenchen.DE).
-+
-+ V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
-+
-+ V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
-+ * realloc: try to expand in both directions
-+ * malloc: swap order of clean-bin strategy;
-+ * realloc: only conditionally expand backwards
-+ * Try not to scavenge used bins
-+ * Use bin counts as a guide to preallocation
-+ * Occasionally bin return list chunks in first scan
-+ * Add a few optimizations from colin@nyx10.cs.du.edu
-+
-+ V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
-+ * faster bin computation & slightly different binning
-+ * merged all consolidations to one part of malloc proper
-+ (eliminating old malloc_find_space & malloc_clean_bin)
-+ * Scan 2 returns chunks (not just 1)
-+ * Propagate failure in realloc if malloc returns 0
-+ * Add stuff to allow compilation on non-ANSI compilers
-+ from kpv@research.att.com
-+
-+ V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
-+ * removed potential for odd address access in prev_chunk
-+ * removed dependency on getpagesize.h
-+ * misc cosmetics and a bit more internal documentation
-+ * anticosmetics: mangled names in macros to evade debugger strangeness
-+ * tested on sparc, hp-700, dec-mips, rs6000
-+ with gcc & native cc (hp, dec only) allowing
-+ Detlefs & Zorn comparison study (in SIGPLAN Notices.)
-+
-+ Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
-+ * Based loosely on libg++-1.2X malloc. (It retains some of the overall
-+ structure of old version, but most details differ.)
-+
-+*/
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi.h modified/Modules/_ctypes/libffi_ios/include/ffi.h
---- orig/Modules/_ctypes/libffi_ios/include/ffi.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffi.h 2015-04-26 08:17:42.000000000 +0800
-@@ -0,0 +1,24 @@
-+#ifdef __arm64__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __i386__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __arm__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __x86_64__
-+
-+#include
-+
-+
-+#endif
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_arm64.h modified/Modules/_ctypes/libffi_ios/include/ffi_arm64.h
---- orig/Modules/_ctypes/libffi_ios/include/ffi_arm64.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffi_arm64.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,492 @@
-+#ifdef __arm64__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green
-+ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
-+
-+ Permission is hereby granted, free of charge, to any person
-+ obtaining a copy of this software and associated documentation
-+ files (the ``Software''), to deal in the Software without
-+ restriction, including without limitation the rights to use, copy,
-+ modify, merge, publish, distribute, sublicense, and/or sell copies
-+ of the Software, and to permit persons to whom the Software is
-+ furnished to do so, subject to the following conditions:
-+
-+ The above copyright notice and this permission notice shall be
-+ included in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+/* -------------------------------------------------------------------
-+ The basic API is described in the README file.
-+
-+ The raw API is designed to bypass some of the argument packing
-+ and unpacking on architectures for which it can be avoided.
-+
-+ The closure API allows interpreted functions to be packaged up
-+ inside a C function pointer, so that they can be called as C functions,
-+ with no understanding on the client side that they are interpreted.
-+ It can also be used in other cases in which it is necessary to package
-+ up a user specified parameter and a function pointer as a single
-+ function pointer.
-+
-+ The closure API must be implemented in order to get its functionality,
-+ e.g. for use by gij. Routines are provided to emulate the raw API
-+ if the underlying platform doesn't allow faster implementation.
-+
-+ More details on the raw and cloure API can be found in:
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-+
-+ and
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-+ -------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_H
-+#define LIBFFI_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* Specify which architecture libffi is configured for. */
-+#ifndef AARCH64
-+#define AARCH64
-+#endif
-+
-+/* ---- System configuration information --------------------------------- */
-+
-+#include
-+
-+#ifndef LIBFFI_ASM
-+
-+#if defined(_MSC_VER) && !defined(__clang__)
-+#define __attribute__(X)
-+#endif
-+
-+#include
-+#include
-+
-+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
-+ But we can find it either under the correct ANSI name, or under GNU
-+ C's internal name. */
-+
-+#define FFI_64_BIT_MAX 9223372036854775807
-+
-+#ifdef LONG_LONG_MAX
-+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-+#else
-+# ifdef LLONG_MAX
-+# define FFI_LONG_LONG_MAX LLONG_MAX
-+# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif /* _AIX52 or newer */
-+# else
-+# ifdef __GNUC__
-+# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-+# endif
-+# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
-+# ifndef __PPC64__
-+# if defined (__IBMC__) || defined (__IBMCPP__)
-+# define FFI_LONG_LONG_MAX LONGLONG_MAX
-+# endif
-+# endif /* __PPC64__ */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif
-+# endif
-+#endif
-+
-+/* The closure code assumes that this works on pointers, i.e. a size_t */
-+/* can hold a pointer. */
-+
-+typedef struct _ffi_type
-+{
-+ size_t size;
-+ unsigned short alignment;
-+ unsigned short type;
-+ struct _ffi_type **elements;
-+} ffi_type;
-+
-+#ifndef LIBFFI_HIDE_BASIC_TYPES
-+#if SCHAR_MAX == 127
-+# define ffi_type_uchar ffi_type_uint8
-+# define ffi_type_schar ffi_type_sint8
-+#else
-+ #error "char size not supported"
-+#endif
-+
-+#if SHRT_MAX == 32767
-+# define ffi_type_ushort ffi_type_uint16
-+# define ffi_type_sshort ffi_type_sint16
-+#elif SHRT_MAX == 2147483647
-+# define ffi_type_ushort ffi_type_uint32
-+# define ffi_type_sshort ffi_type_sint32
-+#else
-+ #error "short size not supported"
-+#endif
-+
-+#if INT_MAX == 32767
-+# define ffi_type_uint ffi_type_uint16
-+# define ffi_type_sint ffi_type_sint16
-+#elif INT_MAX == 2147483647
-+# define ffi_type_uint ffi_type_uint32
-+# define ffi_type_sint ffi_type_sint32
-+#elif INT_MAX == 9223372036854775807
-+# define ffi_type_uint ffi_type_uint64
-+# define ffi_type_sint ffi_type_sint64
-+#else
-+ #error "int size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
-+ #error "no 64-bit data type supported"
-+# endif
-+#elif LONG_MAX != FFI_64_BIT_MAX
-+ #error "long size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# define ffi_type_ulong ffi_type_uint32
-+# define ffi_type_slong ffi_type_sint32
-+#elif LONG_MAX == FFI_64_BIT_MAX
-+# define ffi_type_ulong ffi_type_uint64
-+# define ffi_type_slong ffi_type_sint64
-+#else
-+ #error "long size not supported"
-+#endif
-+
-+/* Need minimal decorations for DLLs to works on Windows. */
-+/* GCC has autoimport and autoexport. Rely on Libtool to */
-+/* help MSVC export from a DLL, but always declare data */
-+/* to be imported for MSVC clients. This costs an extra */
-+/* indirection for MSVC clients using the static version */
-+/* of the library, but don't worry about that. Besides, */
-+/* as a workaround, they can define FFI_BUILDING if they */
-+/* *know* they are going to link with the static library. */
-+#if defined _MSC_VER && !defined FFI_BUILDING
-+#define FFI_EXTERN extern __declspec(dllimport)
-+#else
-+#define FFI_EXTERN extern
-+#endif
-+
-+/* These are defined in types.c */
-+FFI_EXTERN ffi_type ffi_type_void;
-+FFI_EXTERN ffi_type ffi_type_uint8;
-+FFI_EXTERN ffi_type ffi_type_sint8;
-+FFI_EXTERN ffi_type ffi_type_uint16;
-+FFI_EXTERN ffi_type ffi_type_sint16;
-+FFI_EXTERN ffi_type ffi_type_uint32;
-+FFI_EXTERN ffi_type ffi_type_sint32;
-+FFI_EXTERN ffi_type ffi_type_uint64;
-+FFI_EXTERN ffi_type ffi_type_sint64;
-+FFI_EXTERN ffi_type ffi_type_float;
-+FFI_EXTERN ffi_type ffi_type_double;
-+FFI_EXTERN ffi_type ffi_type_pointer;
-+
-+#if 0
-+FFI_EXTERN ffi_type ffi_type_longdouble;
-+#else
-+#define ffi_type_longdouble ffi_type_double
-+#endif
-+
-+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-+FFI_EXTERN ffi_type ffi_type_complex_float;
-+FFI_EXTERN ffi_type ffi_type_complex_double;
-+#if 0
-+FFI_EXTERN ffi_type ffi_type_complex_longdouble;
-+#else
-+#define ffi_type_complex_longdouble ffi_type_complex_double
-+#endif
-+#endif
-+#endif /* LIBFFI_HIDE_BASIC_TYPES */
-+
-+typedef enum {
-+ FFI_OK = 0,
-+ FFI_BAD_TYPEDEF,
-+ FFI_BAD_ABI
-+} ffi_status;
-+
-+typedef unsigned FFI_TYPE;
-+
-+typedef struct {
-+ ffi_abi abi;
-+ unsigned nargs;
-+ ffi_type **arg_types;
-+ ffi_type *rtype;
-+ unsigned bytes;
-+ unsigned flags;
-+#ifdef FFI_EXTRA_CIF_FIELDS
-+ FFI_EXTRA_CIF_FIELDS;
-+#endif
-+} ffi_cif;
-+
-+#if 0
-+/* Used to adjust size/alignment of ffi types. */
-+void ffi_prep_types (ffi_abi abi);
-+#endif
-+
-+/* Used internally, but overridden by some architectures */
-+ffi_status ffi_prep_cif_core(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int isvariadic,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+/* ---- Definitions for the raw API -------------------------------------- */
-+
-+#ifndef FFI_SIZEOF_ARG
-+# if LONG_MAX == 2147483647
-+# define FFI_SIZEOF_ARG 4
-+# elif LONG_MAX == FFI_64_BIT_MAX
-+# define FFI_SIZEOF_ARG 8
-+# endif
-+#endif
-+
-+#ifndef FFI_SIZEOF_JAVA_RAW
-+# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
-+#endif
-+
-+typedef union {
-+ ffi_sarg sint;
-+ ffi_arg uint;
-+ float flt;
-+ char data[FFI_SIZEOF_ARG];
-+ void* ptr;
-+} ffi_raw;
-+
-+#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-+/* This is a special case for mips64/n32 ABI (and perhaps others) where
-+ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
-+typedef union {
-+ signed int sint;
-+ unsigned int uint;
-+ float flt;
-+ char data[FFI_SIZEOF_JAVA_RAW];
-+ void* ptr;
-+} ffi_java_raw;
-+#else
-+typedef ffi_raw ffi_java_raw;
-+#endif
-+
-+
-+void ffi_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_raw *avalue);
-+
-+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-+size_t ffi_raw_size (ffi_cif *cif);
-+
-+/* This is analogous to the raw API, except it uses Java parameter */
-+/* packing, even on 64-bit machines. I.e. on 64-bit machines */
-+/* longs and doubles are followed by an empty 64-bit word. */
-+
-+void ffi_java_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_java_raw *avalue);
-+
-+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-+size_t ffi_java_raw_size (ffi_cif *cif);
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#if FFI_CLOSURES
-+
-+#ifdef _MSC_VER
-+__declspec(align(8))
-+#endif
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+ void (*fun)(ffi_cif*,void*,void**,void*);
-+ void *user_data;
-+#ifdef __GNUC__
-+} ffi_closure __attribute__((aligned (8)));
-+#else
-+} ffi_closure;
-+# ifdef __sgi
-+# pragma pack 0
-+# endif
-+#endif
-+
-+void *ffi_closure_alloc (size_t size, void **code);
-+void ffi_closure_free (void *);
-+
-+ffi_status
-+ffi_prep_closure (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_closure_loc (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data,
-+ void*codeloc);
-+
-+#ifdef __sgi
-+# pragma pack 8
-+#endif
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
-+ void *user_data;
-+
-+} ffi_raw_closure;
-+
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
-+ void *user_data;
-+
-+} ffi_java_raw_closure;
-+
-+ffi_status
-+ffi_prep_raw_closure (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_raw_closure_loc (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+ffi_status
-+ffi_prep_java_raw_closure (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+#endif /* FFI_CLOSURES */
-+
-+/* ---- Public interface definition -------------------------------------- */
-+
-+ffi_status ffi_prep_cif(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+ffi_status ffi_prep_cif_var(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+void ffi_call(ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ void **avalue);
-+
-+/* Useful for eliminating compiler warnings */
-+#define FFI_FN(f) ((void (*)(void))f)
-+
-+/* ---- Definitions shared with assembly code ---------------------------- */
-+
-+#endif
-+
-+/* If these change, update src/mips/ffitarget.h. */
-+#define FFI_TYPE_VOID 0
-+#define FFI_TYPE_INT 1
-+#define FFI_TYPE_FLOAT 2
-+#define FFI_TYPE_DOUBLE 3
-+#if 0
-+#define FFI_TYPE_LONGDOUBLE 4
-+#else
-+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-+#endif
-+#define FFI_TYPE_UINT8 5
-+#define FFI_TYPE_SINT8 6
-+#define FFI_TYPE_UINT16 7
-+#define FFI_TYPE_SINT16 8
-+#define FFI_TYPE_UINT32 9
-+#define FFI_TYPE_SINT32 10
-+#define FFI_TYPE_UINT64 11
-+#define FFI_TYPE_SINT64 12
-+#define FFI_TYPE_STRUCT 13
-+#define FFI_TYPE_POINTER 14
-+#define FFI_TYPE_COMPLEX 15
-+
-+/* This should always refer to the last type code (for sanity checks) */
-+#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_armv7.h modified/Modules/_ctypes/libffi_ios/include/ffi_armv7.h
---- orig/Modules/_ctypes/libffi_ios/include/ffi_armv7.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffi_armv7.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,492 @@
-+#ifdef __arm__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green
-+ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
-+
-+ Permission is hereby granted, free of charge, to any person
-+ obtaining a copy of this software and associated documentation
-+ files (the ``Software''), to deal in the Software without
-+ restriction, including without limitation the rights to use, copy,
-+ modify, merge, publish, distribute, sublicense, and/or sell copies
-+ of the Software, and to permit persons to whom the Software is
-+ furnished to do so, subject to the following conditions:
-+
-+ The above copyright notice and this permission notice shall be
-+ included in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+/* -------------------------------------------------------------------
-+ The basic API is described in the README file.
-+
-+ The raw API is designed to bypass some of the argument packing
-+ and unpacking on architectures for which it can be avoided.
-+
-+ The closure API allows interpreted functions to be packaged up
-+ inside a C function pointer, so that they can be called as C functions,
-+ with no understanding on the client side that they are interpreted.
-+ It can also be used in other cases in which it is necessary to package
-+ up a user specified parameter and a function pointer as a single
-+ function pointer.
-+
-+ The closure API must be implemented in order to get its functionality,
-+ e.g. for use by gij. Routines are provided to emulate the raw API
-+ if the underlying platform doesn't allow faster implementation.
-+
-+ More details on the raw and cloure API can be found in:
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-+
-+ and
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-+ -------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_H
-+#define LIBFFI_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* Specify which architecture libffi is configured for. */
-+#ifndef ARM
-+#define ARM
-+#endif
-+
-+/* ---- System configuration information --------------------------------- */
-+
-+#include
-+
-+#ifndef LIBFFI_ASM
-+
-+#if defined(_MSC_VER) && !defined(__clang__)
-+#define __attribute__(X)
-+#endif
-+
-+#include
-+#include
-+
-+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
-+ But we can find it either under the correct ANSI name, or under GNU
-+ C's internal name. */
-+
-+#define FFI_64_BIT_MAX 9223372036854775807
-+
-+#ifdef LONG_LONG_MAX
-+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-+#else
-+# ifdef LLONG_MAX
-+# define FFI_LONG_LONG_MAX LLONG_MAX
-+# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif /* _AIX52 or newer */
-+# else
-+# ifdef __GNUC__
-+# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-+# endif
-+# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
-+# ifndef __PPC64__
-+# if defined (__IBMC__) || defined (__IBMCPP__)
-+# define FFI_LONG_LONG_MAX LONGLONG_MAX
-+# endif
-+# endif /* __PPC64__ */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif
-+# endif
-+#endif
-+
-+/* The closure code assumes that this works on pointers, i.e. a size_t */
-+/* can hold a pointer. */
-+
-+typedef struct _ffi_type
-+{
-+ size_t size;
-+ unsigned short alignment;
-+ unsigned short type;
-+ struct _ffi_type **elements;
-+} ffi_type;
-+
-+#ifndef LIBFFI_HIDE_BASIC_TYPES
-+#if SCHAR_MAX == 127
-+# define ffi_type_uchar ffi_type_uint8
-+# define ffi_type_schar ffi_type_sint8
-+#else
-+ #error "char size not supported"
-+#endif
-+
-+#if SHRT_MAX == 32767
-+# define ffi_type_ushort ffi_type_uint16
-+# define ffi_type_sshort ffi_type_sint16
-+#elif SHRT_MAX == 2147483647
-+# define ffi_type_ushort ffi_type_uint32
-+# define ffi_type_sshort ffi_type_sint32
-+#else
-+ #error "short size not supported"
-+#endif
-+
-+#if INT_MAX == 32767
-+# define ffi_type_uint ffi_type_uint16
-+# define ffi_type_sint ffi_type_sint16
-+#elif INT_MAX == 2147483647
-+# define ffi_type_uint ffi_type_uint32
-+# define ffi_type_sint ffi_type_sint32
-+#elif INT_MAX == 9223372036854775807
-+# define ffi_type_uint ffi_type_uint64
-+# define ffi_type_sint ffi_type_sint64
-+#else
-+ #error "int size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
-+ #error "no 64-bit data type supported"
-+# endif
-+#elif LONG_MAX != FFI_64_BIT_MAX
-+ #error "long size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# define ffi_type_ulong ffi_type_uint32
-+# define ffi_type_slong ffi_type_sint32
-+#elif LONG_MAX == FFI_64_BIT_MAX
-+# define ffi_type_ulong ffi_type_uint64
-+# define ffi_type_slong ffi_type_sint64
-+#else
-+ #error "long size not supported"
-+#endif
-+
-+/* Need minimal decorations for DLLs to works on Windows. */
-+/* GCC has autoimport and autoexport. Rely on Libtool to */
-+/* help MSVC export from a DLL, but always declare data */
-+/* to be imported for MSVC clients. This costs an extra */
-+/* indirection for MSVC clients using the static version */
-+/* of the library, but don't worry about that. Besides, */
-+/* as a workaround, they can define FFI_BUILDING if they */
-+/* *know* they are going to link with the static library. */
-+#if defined _MSC_VER && !defined FFI_BUILDING
-+#define FFI_EXTERN extern __declspec(dllimport)
-+#else
-+#define FFI_EXTERN extern
-+#endif
-+
-+/* These are defined in types.c */
-+FFI_EXTERN ffi_type ffi_type_void;
-+FFI_EXTERN ffi_type ffi_type_uint8;
-+FFI_EXTERN ffi_type ffi_type_sint8;
-+FFI_EXTERN ffi_type ffi_type_uint16;
-+FFI_EXTERN ffi_type ffi_type_sint16;
-+FFI_EXTERN ffi_type ffi_type_uint32;
-+FFI_EXTERN ffi_type ffi_type_sint32;
-+FFI_EXTERN ffi_type ffi_type_uint64;
-+FFI_EXTERN ffi_type ffi_type_sint64;
-+FFI_EXTERN ffi_type ffi_type_float;
-+FFI_EXTERN ffi_type ffi_type_double;
-+FFI_EXTERN ffi_type ffi_type_pointer;
-+
-+#if 0
-+FFI_EXTERN ffi_type ffi_type_longdouble;
-+#else
-+#define ffi_type_longdouble ffi_type_double
-+#endif
-+
-+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-+FFI_EXTERN ffi_type ffi_type_complex_float;
-+FFI_EXTERN ffi_type ffi_type_complex_double;
-+#if 0
-+FFI_EXTERN ffi_type ffi_type_complex_longdouble;
-+#else
-+#define ffi_type_complex_longdouble ffi_type_complex_double
-+#endif
-+#endif
-+#endif /* LIBFFI_HIDE_BASIC_TYPES */
-+
-+typedef enum {
-+ FFI_OK = 0,
-+ FFI_BAD_TYPEDEF,
-+ FFI_BAD_ABI
-+} ffi_status;
-+
-+typedef unsigned FFI_TYPE;
-+
-+typedef struct {
-+ ffi_abi abi;
-+ unsigned nargs;
-+ ffi_type **arg_types;
-+ ffi_type *rtype;
-+ unsigned bytes;
-+ unsigned flags;
-+#ifdef FFI_EXTRA_CIF_FIELDS
-+ FFI_EXTRA_CIF_FIELDS;
-+#endif
-+} ffi_cif;
-+
-+#if 0
-+/* Used to adjust size/alignment of ffi types. */
-+void ffi_prep_types (ffi_abi abi);
-+#endif
-+
-+/* Used internally, but overridden by some architectures */
-+ffi_status ffi_prep_cif_core(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int isvariadic,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+/* ---- Definitions for the raw API -------------------------------------- */
-+
-+#ifndef FFI_SIZEOF_ARG
-+# if LONG_MAX == 2147483647
-+# define FFI_SIZEOF_ARG 4
-+# elif LONG_MAX == FFI_64_BIT_MAX
-+# define FFI_SIZEOF_ARG 8
-+# endif
-+#endif
-+
-+#ifndef FFI_SIZEOF_JAVA_RAW
-+# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
-+#endif
-+
-+typedef union {
-+ ffi_sarg sint;
-+ ffi_arg uint;
-+ float flt;
-+ char data[FFI_SIZEOF_ARG];
-+ void* ptr;
-+} ffi_raw;
-+
-+#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-+/* This is a special case for mips64/n32 ABI (and perhaps others) where
-+ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
-+typedef union {
-+ signed int sint;
-+ unsigned int uint;
-+ float flt;
-+ char data[FFI_SIZEOF_JAVA_RAW];
-+ void* ptr;
-+} ffi_java_raw;
-+#else
-+typedef ffi_raw ffi_java_raw;
-+#endif
-+
-+
-+void ffi_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_raw *avalue);
-+
-+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-+size_t ffi_raw_size (ffi_cif *cif);
-+
-+/* This is analogous to the raw API, except it uses Java parameter */
-+/* packing, even on 64-bit machines. I.e. on 64-bit machines */
-+/* longs and doubles are followed by an empty 64-bit word. */
-+
-+void ffi_java_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_java_raw *avalue);
-+
-+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-+size_t ffi_java_raw_size (ffi_cif *cif);
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#if FFI_CLOSURES
-+
-+#ifdef _MSC_VER
-+__declspec(align(8))
-+#endif
-+typedef struct {
-+#if 1
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+ void (*fun)(ffi_cif*,void*,void**,void*);
-+ void *user_data;
-+#ifdef __GNUC__
-+} ffi_closure __attribute__((aligned (8)));
-+#else
-+} ffi_closure;
-+# ifdef __sgi
-+# pragma pack 0
-+# endif
-+#endif
-+
-+void *ffi_closure_alloc (size_t size, void **code);
-+void ffi_closure_free (void *);
-+
-+ffi_status
-+ffi_prep_closure (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_closure_loc (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data,
-+ void*codeloc);
-+
-+#ifdef __sgi
-+# pragma pack 8
-+#endif
-+typedef struct {
-+#if 1
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
-+ void *user_data;
-+
-+} ffi_raw_closure;
-+
-+typedef struct {
-+#if 1
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
-+ void *user_data;
-+
-+} ffi_java_raw_closure;
-+
-+ffi_status
-+ffi_prep_raw_closure (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_raw_closure_loc (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+ffi_status
-+ffi_prep_java_raw_closure (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+#endif /* FFI_CLOSURES */
-+
-+/* ---- Public interface definition -------------------------------------- */
-+
-+ffi_status ffi_prep_cif(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+ffi_status ffi_prep_cif_var(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+void ffi_call(ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ void **avalue);
-+
-+/* Useful for eliminating compiler warnings */
-+#define FFI_FN(f) ((void (*)(void))f)
-+
-+/* ---- Definitions shared with assembly code ---------------------------- */
-+
-+#endif
-+
-+/* If these change, update src/mips/ffitarget.h. */
-+#define FFI_TYPE_VOID 0
-+#define FFI_TYPE_INT 1
-+#define FFI_TYPE_FLOAT 2
-+#define FFI_TYPE_DOUBLE 3
-+#if 0
-+#define FFI_TYPE_LONGDOUBLE 4
-+#else
-+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-+#endif
-+#define FFI_TYPE_UINT8 5
-+#define FFI_TYPE_SINT8 6
-+#define FFI_TYPE_UINT16 7
-+#define FFI_TYPE_SINT16 8
-+#define FFI_TYPE_UINT32 9
-+#define FFI_TYPE_SINT32 10
-+#define FFI_TYPE_UINT64 11
-+#define FFI_TYPE_SINT64 12
-+#define FFI_TYPE_STRUCT 13
-+#define FFI_TYPE_POINTER 14
-+#define FFI_TYPE_COMPLEX 15
-+
-+/* This should always refer to the last type code (for sanity checks) */
-+#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_common.h modified/Modules/_ctypes/libffi_ios/include/ffi_common.h
---- orig/Modules/_ctypes/libffi_ios/include/ffi_common.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffi_common.h 2015-04-26 08:17:42.000000000 +0800
-@@ -0,0 +1,132 @@
-+/* -----------------------------------------------------------------------
-+ ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green
-+ Copyright (C) 2007 Free Software Foundation, Inc
-+ Copyright (c) 1996 Red Hat, Inc.
-+
-+ Common internal definitions and macros. Only necessary for building
-+ libffi.
-+ ----------------------------------------------------------------------- */
-+
-+#ifndef FFI_COMMON_H
-+#define FFI_COMMON_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+#include
-+
-+/* Do not move this. Some versions of AIX are very picky about where
-+ this is positioned. */
-+#ifdef __GNUC__
-+# if HAVE_ALLOCA_H
-+# include
-+# else
-+ /* mingw64 defines this already in malloc.h. */
-+# ifndef alloca
-+# define alloca __builtin_alloca
-+# endif
-+# endif
-+# define MAYBE_UNUSED __attribute__((__unused__))
-+#else
-+# define MAYBE_UNUSED
-+# if HAVE_ALLOCA_H
-+# include
-+# else
-+# ifdef _AIX
-+# pragma alloca
-+# else
-+# ifndef alloca /* predefined by HP cc +Olibcalls */
-+# ifdef _MSC_VER
-+# define alloca _alloca
-+# else
-+char *alloca ();
-+# endif
-+# endif
-+# endif
-+# endif
-+#endif
-+
-+/* Check for the existence of memcpy. */
-+#if STDC_HEADERS
-+# include
-+#else
-+# ifndef HAVE_MEMCPY
-+# define memcpy(d, s, n) bcopy ((s), (d), (n))
-+# endif
-+#endif
-+
-+#if defined(FFI_DEBUG)
-+#include
-+#endif
-+
-+#ifdef FFI_DEBUG
-+void ffi_assert(char *expr, char *file, int line);
-+void ffi_stop_here(void);
-+void ffi_type_test(ffi_type *a, char *file, int line);
-+
-+#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
-+#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
-+#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
-+#else
-+#define FFI_ASSERT(x)
-+#define FFI_ASSERT_AT(x, f, l)
-+#define FFI_ASSERT_VALID_TYPE(x)
-+#endif
-+
-+#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
-+#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
-+
-+/* Perform machine dependent cif processing */
-+ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
-+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
-+ unsigned int nfixedargs, unsigned int ntotalargs);
-+
-+/* Extended cif, used in callback from assembly routine */
-+typedef struct
-+{
-+ ffi_cif *cif;
-+ void *rvalue;
-+ void **avalue;
-+} extended_cif;
-+
-+/* Terse sized type definitions. */
-+#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
-+typedef unsigned char UINT8;
-+typedef signed char SINT8;
-+typedef unsigned short UINT16;
-+typedef signed short SINT16;
-+typedef unsigned int UINT32;
-+typedef signed int SINT32;
-+# ifdef _MSC_VER
-+typedef unsigned __int64 UINT64;
-+typedef signed __int64 SINT64;
-+# else
-+# include
-+typedef uint64_t UINT64;
-+typedef int64_t SINT64;
-+# endif
-+#else
-+typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
-+typedef signed int SINT8 __attribute__((__mode__(__QI__)));
-+typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
-+typedef signed int SINT16 __attribute__((__mode__(__HI__)));
-+typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
-+typedef signed int SINT32 __attribute__((__mode__(__SI__)));
-+typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
-+typedef signed int SINT64 __attribute__((__mode__(__DI__)));
-+#endif
-+
-+typedef float FLOAT32;
-+
-+#ifndef __GNUC__
-+#define __builtin_expect(x, expected_value) (x)
-+#endif
-+#define LIKELY(x) __builtin_expect(!!(x),1)
-+#define UNLIKELY(x) __builtin_expect((x)!=0,0)
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_i386.h modified/Modules/_ctypes/libffi_ios/include/ffi_i386.h
---- orig/Modules/_ctypes/libffi_ios/include/ffi_i386.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffi_i386.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,492 @@
-+#ifdef __i386__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green
-+ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
-+
-+ Permission is hereby granted, free of charge, to any person
-+ obtaining a copy of this software and associated documentation
-+ files (the ``Software''), to deal in the Software without
-+ restriction, including without limitation the rights to use, copy,
-+ modify, merge, publish, distribute, sublicense, and/or sell copies
-+ of the Software, and to permit persons to whom the Software is
-+ furnished to do so, subject to the following conditions:
-+
-+ The above copyright notice and this permission notice shall be
-+ included in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+/* -------------------------------------------------------------------
-+ The basic API is described in the README file.
-+
-+ The raw API is designed to bypass some of the argument packing
-+ and unpacking on architectures for which it can be avoided.
-+
-+ The closure API allows interpreted functions to be packaged up
-+ inside a C function pointer, so that they can be called as C functions,
-+ with no understanding on the client side that they are interpreted.
-+ It can also be used in other cases in which it is necessary to package
-+ up a user specified parameter and a function pointer as a single
-+ function pointer.
-+
-+ The closure API must be implemented in order to get its functionality,
-+ e.g. for use by gij. Routines are provided to emulate the raw API
-+ if the underlying platform doesn't allow faster implementation.
-+
-+ More details on the raw and cloure API can be found in:
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-+
-+ and
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-+ -------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_H
-+#define LIBFFI_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* Specify which architecture libffi is configured for. */
-+#ifndef X86_DARWIN
-+#define X86_DARWIN
-+#endif
-+
-+/* ---- System configuration information --------------------------------- */
-+
-+#include
-+
-+#ifndef LIBFFI_ASM
-+
-+#if defined(_MSC_VER) && !defined(__clang__)
-+#define __attribute__(X)
-+#endif
-+
-+#include
-+#include
-+
-+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
-+ But we can find it either under the correct ANSI name, or under GNU
-+ C's internal name. */
-+
-+#define FFI_64_BIT_MAX 9223372036854775807
-+
-+#ifdef LONG_LONG_MAX
-+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-+#else
-+# ifdef LLONG_MAX
-+# define FFI_LONG_LONG_MAX LLONG_MAX
-+# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif /* _AIX52 or newer */
-+# else
-+# ifdef __GNUC__
-+# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-+# endif
-+# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
-+# ifndef __PPC64__
-+# if defined (__IBMC__) || defined (__IBMCPP__)
-+# define FFI_LONG_LONG_MAX LONGLONG_MAX
-+# endif
-+# endif /* __PPC64__ */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif
-+# endif
-+#endif
-+
-+/* The closure code assumes that this works on pointers, i.e. a size_t */
-+/* can hold a pointer. */
-+
-+typedef struct _ffi_type
-+{
-+ size_t size;
-+ unsigned short alignment;
-+ unsigned short type;
-+ struct _ffi_type **elements;
-+} ffi_type;
-+
-+#ifndef LIBFFI_HIDE_BASIC_TYPES
-+#if SCHAR_MAX == 127
-+# define ffi_type_uchar ffi_type_uint8
-+# define ffi_type_schar ffi_type_sint8
-+#else
-+ #error "char size not supported"
-+#endif
-+
-+#if SHRT_MAX == 32767
-+# define ffi_type_ushort ffi_type_uint16
-+# define ffi_type_sshort ffi_type_sint16
-+#elif SHRT_MAX == 2147483647
-+# define ffi_type_ushort ffi_type_uint32
-+# define ffi_type_sshort ffi_type_sint32
-+#else
-+ #error "short size not supported"
-+#endif
-+
-+#if INT_MAX == 32767
-+# define ffi_type_uint ffi_type_uint16
-+# define ffi_type_sint ffi_type_sint16
-+#elif INT_MAX == 2147483647
-+# define ffi_type_uint ffi_type_uint32
-+# define ffi_type_sint ffi_type_sint32
-+#elif INT_MAX == 9223372036854775807
-+# define ffi_type_uint ffi_type_uint64
-+# define ffi_type_sint ffi_type_sint64
-+#else
-+ #error "int size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
-+ #error "no 64-bit data type supported"
-+# endif
-+#elif LONG_MAX != FFI_64_BIT_MAX
-+ #error "long size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# define ffi_type_ulong ffi_type_uint32
-+# define ffi_type_slong ffi_type_sint32
-+#elif LONG_MAX == FFI_64_BIT_MAX
-+# define ffi_type_ulong ffi_type_uint64
-+# define ffi_type_slong ffi_type_sint64
-+#else
-+ #error "long size not supported"
-+#endif
-+
-+/* Need minimal decorations for DLLs to works on Windows. */
-+/* GCC has autoimport and autoexport. Rely on Libtool to */
-+/* help MSVC export from a DLL, but always declare data */
-+/* to be imported for MSVC clients. This costs an extra */
-+/* indirection for MSVC clients using the static version */
-+/* of the library, but don't worry about that. Besides, */
-+/* as a workaround, they can define FFI_BUILDING if they */
-+/* *know* they are going to link with the static library. */
-+#if defined _MSC_VER && !defined FFI_BUILDING
-+#define FFI_EXTERN extern __declspec(dllimport)
-+#else
-+#define FFI_EXTERN extern
-+#endif
-+
-+/* These are defined in types.c */
-+FFI_EXTERN ffi_type ffi_type_void;
-+FFI_EXTERN ffi_type ffi_type_uint8;
-+FFI_EXTERN ffi_type ffi_type_sint8;
-+FFI_EXTERN ffi_type ffi_type_uint16;
-+FFI_EXTERN ffi_type ffi_type_sint16;
-+FFI_EXTERN ffi_type ffi_type_uint32;
-+FFI_EXTERN ffi_type ffi_type_sint32;
-+FFI_EXTERN ffi_type ffi_type_uint64;
-+FFI_EXTERN ffi_type ffi_type_sint64;
-+FFI_EXTERN ffi_type ffi_type_float;
-+FFI_EXTERN ffi_type ffi_type_double;
-+FFI_EXTERN ffi_type ffi_type_pointer;
-+
-+#if 1
-+FFI_EXTERN ffi_type ffi_type_longdouble;
-+#else
-+#define ffi_type_longdouble ffi_type_double
-+#endif
-+
-+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-+FFI_EXTERN ffi_type ffi_type_complex_float;
-+FFI_EXTERN ffi_type ffi_type_complex_double;
-+#if 1
-+FFI_EXTERN ffi_type ffi_type_complex_longdouble;
-+#else
-+#define ffi_type_complex_longdouble ffi_type_complex_double
-+#endif
-+#endif
-+#endif /* LIBFFI_HIDE_BASIC_TYPES */
-+
-+typedef enum {
-+ FFI_OK = 0,
-+ FFI_BAD_TYPEDEF,
-+ FFI_BAD_ABI
-+} ffi_status;
-+
-+typedef unsigned FFI_TYPE;
-+
-+typedef struct {
-+ ffi_abi abi;
-+ unsigned nargs;
-+ ffi_type **arg_types;
-+ ffi_type *rtype;
-+ unsigned bytes;
-+ unsigned flags;
-+#ifdef FFI_EXTRA_CIF_FIELDS
-+ FFI_EXTRA_CIF_FIELDS;
-+#endif
-+} ffi_cif;
-+
-+#if 0
-+/* Used to adjust size/alignment of ffi types. */
-+void ffi_prep_types (ffi_abi abi);
-+#endif
-+
-+/* Used internally, but overridden by some architectures */
-+ffi_status ffi_prep_cif_core(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int isvariadic,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+/* ---- Definitions for the raw API -------------------------------------- */
-+
-+#ifndef FFI_SIZEOF_ARG
-+# if LONG_MAX == 2147483647
-+# define FFI_SIZEOF_ARG 4
-+# elif LONG_MAX == FFI_64_BIT_MAX
-+# define FFI_SIZEOF_ARG 8
-+# endif
-+#endif
-+
-+#ifndef FFI_SIZEOF_JAVA_RAW
-+# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
-+#endif
-+
-+typedef union {
-+ ffi_sarg sint;
-+ ffi_arg uint;
-+ float flt;
-+ char data[FFI_SIZEOF_ARG];
-+ void* ptr;
-+} ffi_raw;
-+
-+#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-+/* This is a special case for mips64/n32 ABI (and perhaps others) where
-+ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
-+typedef union {
-+ signed int sint;
-+ unsigned int uint;
-+ float flt;
-+ char data[FFI_SIZEOF_JAVA_RAW];
-+ void* ptr;
-+} ffi_java_raw;
-+#else
-+typedef ffi_raw ffi_java_raw;
-+#endif
-+
-+
-+void ffi_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_raw *avalue);
-+
-+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-+size_t ffi_raw_size (ffi_cif *cif);
-+
-+/* This is analogous to the raw API, except it uses Java parameter */
-+/* packing, even on 64-bit machines. I.e. on 64-bit machines */
-+/* longs and doubles are followed by an empty 64-bit word. */
-+
-+void ffi_java_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_java_raw *avalue);
-+
-+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-+size_t ffi_java_raw_size (ffi_cif *cif);
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#if FFI_CLOSURES
-+
-+#ifdef _MSC_VER
-+__declspec(align(8))
-+#endif
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+ void (*fun)(ffi_cif*,void*,void**,void*);
-+ void *user_data;
-+#ifdef __GNUC__
-+} ffi_closure __attribute__((aligned (8)));
-+#else
-+} ffi_closure;
-+# ifdef __sgi
-+# pragma pack 0
-+# endif
-+#endif
-+
-+void *ffi_closure_alloc (size_t size, void **code);
-+void ffi_closure_free (void *);
-+
-+ffi_status
-+ffi_prep_closure (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_closure_loc (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data,
-+ void*codeloc);
-+
-+#ifdef __sgi
-+# pragma pack 8
-+#endif
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
-+ void *user_data;
-+
-+} ffi_raw_closure;
-+
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
-+ void *user_data;
-+
-+} ffi_java_raw_closure;
-+
-+ffi_status
-+ffi_prep_raw_closure (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_raw_closure_loc (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+ffi_status
-+ffi_prep_java_raw_closure (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+#endif /* FFI_CLOSURES */
-+
-+/* ---- Public interface definition -------------------------------------- */
-+
-+ffi_status ffi_prep_cif(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+ffi_status ffi_prep_cif_var(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+void ffi_call(ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ void **avalue);
-+
-+/* Useful for eliminating compiler warnings */
-+#define FFI_FN(f) ((void (*)(void))f)
-+
-+/* ---- Definitions shared with assembly code ---------------------------- */
-+
-+#endif
-+
-+/* If these change, update src/mips/ffitarget.h. */
-+#define FFI_TYPE_VOID 0
-+#define FFI_TYPE_INT 1
-+#define FFI_TYPE_FLOAT 2
-+#define FFI_TYPE_DOUBLE 3
-+#if 1
-+#define FFI_TYPE_LONGDOUBLE 4
-+#else
-+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-+#endif
-+#define FFI_TYPE_UINT8 5
-+#define FFI_TYPE_SINT8 6
-+#define FFI_TYPE_UINT16 7
-+#define FFI_TYPE_SINT16 8
-+#define FFI_TYPE_UINT32 9
-+#define FFI_TYPE_SINT32 10
-+#define FFI_TYPE_UINT64 11
-+#define FFI_TYPE_SINT64 12
-+#define FFI_TYPE_STRUCT 13
-+#define FFI_TYPE_POINTER 14
-+#define FFI_TYPE_COMPLEX 15
-+
-+/* This should always refer to the last type code (for sanity checks) */
-+#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h modified/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h
---- orig/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,492 @@
-+#ifdef __x86_64__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green
-+ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
-+
-+ Permission is hereby granted, free of charge, to any person
-+ obtaining a copy of this software and associated documentation
-+ files (the ``Software''), to deal in the Software without
-+ restriction, including without limitation the rights to use, copy,
-+ modify, merge, publish, distribute, sublicense, and/or sell copies
-+ of the Software, and to permit persons to whom the Software is
-+ furnished to do so, subject to the following conditions:
-+
-+ The above copyright notice and this permission notice shall be
-+ included in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+/* -------------------------------------------------------------------
-+ The basic API is described in the README file.
-+
-+ The raw API is designed to bypass some of the argument packing
-+ and unpacking on architectures for which it can be avoided.
-+
-+ The closure API allows interpreted functions to be packaged up
-+ inside a C function pointer, so that they can be called as C functions,
-+ with no understanding on the client side that they are interpreted.
-+ It can also be used in other cases in which it is necessary to package
-+ up a user specified parameter and a function pointer as a single
-+ function pointer.
-+
-+ The closure API must be implemented in order to get its functionality,
-+ e.g. for use by gij. Routines are provided to emulate the raw API
-+ if the underlying platform doesn't allow faster implementation.
-+
-+ More details on the raw and cloure API can be found in:
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-+
-+ and
-+
-+ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
-+ -------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_H
-+#define LIBFFI_H
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+/* Specify which architecture libffi is configured for. */
-+#ifndef X86_DARWIN
-+#define X86_DARWIN
-+#endif
-+
-+/* ---- System configuration information --------------------------------- */
-+
-+#include
-+
-+#ifndef LIBFFI_ASM
-+
-+#if defined(_MSC_VER) && !defined(__clang__)
-+#define __attribute__(X)
-+#endif
-+
-+#include
-+#include
-+
-+/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
-+ But we can find it either under the correct ANSI name, or under GNU
-+ C's internal name. */
-+
-+#define FFI_64_BIT_MAX 9223372036854775807
-+
-+#ifdef LONG_LONG_MAX
-+# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-+#else
-+# ifdef LLONG_MAX
-+# define FFI_LONG_LONG_MAX LLONG_MAX
-+# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif /* _AIX52 or newer */
-+# else
-+# ifdef __GNUC__
-+# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-+# endif
-+# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
-+# ifndef __PPC64__
-+# if defined (__IBMC__) || defined (__IBMCPP__)
-+# define FFI_LONG_LONG_MAX LONGLONG_MAX
-+# endif
-+# endif /* __PPC64__ */
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807LL
-+# endif
-+# endif
-+#endif
-+
-+/* The closure code assumes that this works on pointers, i.e. a size_t */
-+/* can hold a pointer. */
-+
-+typedef struct _ffi_type
-+{
-+ size_t size;
-+ unsigned short alignment;
-+ unsigned short type;
-+ struct _ffi_type **elements;
-+} ffi_type;
-+
-+#ifndef LIBFFI_HIDE_BASIC_TYPES
-+#if SCHAR_MAX == 127
-+# define ffi_type_uchar ffi_type_uint8
-+# define ffi_type_schar ffi_type_sint8
-+#else
-+ #error "char size not supported"
-+#endif
-+
-+#if SHRT_MAX == 32767
-+# define ffi_type_ushort ffi_type_uint16
-+# define ffi_type_sshort ffi_type_sint16
-+#elif SHRT_MAX == 2147483647
-+# define ffi_type_ushort ffi_type_uint32
-+# define ffi_type_sshort ffi_type_sint32
-+#else
-+ #error "short size not supported"
-+#endif
-+
-+#if INT_MAX == 32767
-+# define ffi_type_uint ffi_type_uint16
-+# define ffi_type_sint ffi_type_sint16
-+#elif INT_MAX == 2147483647
-+# define ffi_type_uint ffi_type_uint32
-+# define ffi_type_sint ffi_type_sint32
-+#elif INT_MAX == 9223372036854775807
-+# define ffi_type_uint ffi_type_uint64
-+# define ffi_type_sint ffi_type_sint64
-+#else
-+ #error "int size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
-+ #error "no 64-bit data type supported"
-+# endif
-+#elif LONG_MAX != FFI_64_BIT_MAX
-+ #error "long size not supported"
-+#endif
-+
-+#if LONG_MAX == 2147483647
-+# define ffi_type_ulong ffi_type_uint32
-+# define ffi_type_slong ffi_type_sint32
-+#elif LONG_MAX == FFI_64_BIT_MAX
-+# define ffi_type_ulong ffi_type_uint64
-+# define ffi_type_slong ffi_type_sint64
-+#else
-+ #error "long size not supported"
-+#endif
-+
-+/* Need minimal decorations for DLLs to works on Windows. */
-+/* GCC has autoimport and autoexport. Rely on Libtool to */
-+/* help MSVC export from a DLL, but always declare data */
-+/* to be imported for MSVC clients. This costs an extra */
-+/* indirection for MSVC clients using the static version */
-+/* of the library, but don't worry about that. Besides, */
-+/* as a workaround, they can define FFI_BUILDING if they */
-+/* *know* they are going to link with the static library. */
-+#if defined _MSC_VER && !defined FFI_BUILDING
-+#define FFI_EXTERN extern __declspec(dllimport)
-+#else
-+#define FFI_EXTERN extern
-+#endif
-+
-+/* These are defined in types.c */
-+FFI_EXTERN ffi_type ffi_type_void;
-+FFI_EXTERN ffi_type ffi_type_uint8;
-+FFI_EXTERN ffi_type ffi_type_sint8;
-+FFI_EXTERN ffi_type ffi_type_uint16;
-+FFI_EXTERN ffi_type ffi_type_sint16;
-+FFI_EXTERN ffi_type ffi_type_uint32;
-+FFI_EXTERN ffi_type ffi_type_sint32;
-+FFI_EXTERN ffi_type ffi_type_uint64;
-+FFI_EXTERN ffi_type ffi_type_sint64;
-+FFI_EXTERN ffi_type ffi_type_float;
-+FFI_EXTERN ffi_type ffi_type_double;
-+FFI_EXTERN ffi_type ffi_type_pointer;
-+
-+#if 1
-+FFI_EXTERN ffi_type ffi_type_longdouble;
-+#else
-+#define ffi_type_longdouble ffi_type_double
-+#endif
-+
-+#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
-+FFI_EXTERN ffi_type ffi_type_complex_float;
-+FFI_EXTERN ffi_type ffi_type_complex_double;
-+#if 1
-+FFI_EXTERN ffi_type ffi_type_complex_longdouble;
-+#else
-+#define ffi_type_complex_longdouble ffi_type_complex_double
-+#endif
-+#endif
-+#endif /* LIBFFI_HIDE_BASIC_TYPES */
-+
-+typedef enum {
-+ FFI_OK = 0,
-+ FFI_BAD_TYPEDEF,
-+ FFI_BAD_ABI
-+} ffi_status;
-+
-+typedef unsigned FFI_TYPE;
-+
-+typedef struct {
-+ ffi_abi abi;
-+ unsigned nargs;
-+ ffi_type **arg_types;
-+ ffi_type *rtype;
-+ unsigned bytes;
-+ unsigned flags;
-+#ifdef FFI_EXTRA_CIF_FIELDS
-+ FFI_EXTRA_CIF_FIELDS;
-+#endif
-+} ffi_cif;
-+
-+#if 0
-+/* Used to adjust size/alignment of ffi types. */
-+void ffi_prep_types (ffi_abi abi);
-+#endif
-+
-+/* Used internally, but overridden by some architectures */
-+ffi_status ffi_prep_cif_core(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int isvariadic,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+/* ---- Definitions for the raw API -------------------------------------- */
-+
-+#ifndef FFI_SIZEOF_ARG
-+# if LONG_MAX == 2147483647
-+# define FFI_SIZEOF_ARG 4
-+# elif LONG_MAX == FFI_64_BIT_MAX
-+# define FFI_SIZEOF_ARG 8
-+# endif
-+#endif
-+
-+#ifndef FFI_SIZEOF_JAVA_RAW
-+# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
-+#endif
-+
-+typedef union {
-+ ffi_sarg sint;
-+ ffi_arg uint;
-+ float flt;
-+ char data[FFI_SIZEOF_ARG];
-+ void* ptr;
-+} ffi_raw;
-+
-+#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
-+/* This is a special case for mips64/n32 ABI (and perhaps others) where
-+ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
-+typedef union {
-+ signed int sint;
-+ unsigned int uint;
-+ float flt;
-+ char data[FFI_SIZEOF_JAVA_RAW];
-+ void* ptr;
-+} ffi_java_raw;
-+#else
-+typedef ffi_raw ffi_java_raw;
-+#endif
-+
-+
-+void ffi_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_raw *avalue);
-+
-+void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-+void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-+size_t ffi_raw_size (ffi_cif *cif);
-+
-+/* This is analogous to the raw API, except it uses Java parameter */
-+/* packing, even on 64-bit machines. I.e. on 64-bit machines */
-+/* longs and doubles are followed by an empty 64-bit word. */
-+
-+void ffi_java_raw_call (ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ ffi_java_raw *avalue);
-+
-+void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
-+void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
-+size_t ffi_java_raw_size (ffi_cif *cif);
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#if FFI_CLOSURES
-+
-+#ifdef _MSC_VER
-+__declspec(align(8))
-+#endif
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+ void (*fun)(ffi_cif*,void*,void**,void*);
-+ void *user_data;
-+#ifdef __GNUC__
-+} ffi_closure __attribute__((aligned (8)));
-+#else
-+} ffi_closure;
-+# ifdef __sgi
-+# pragma pack 0
-+# endif
-+#endif
-+
-+void *ffi_closure_alloc (size_t size, void **code);
-+void ffi_closure_free (void *);
-+
-+ffi_status
-+ffi_prep_closure (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_closure_loc (ffi_closure*,
-+ ffi_cif *,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data,
-+ void*codeloc);
-+
-+#ifdef __sgi
-+# pragma pack 8
-+#endif
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
-+ void *user_data;
-+
-+} ffi_raw_closure;
-+
-+typedef struct {
-+#if 0
-+ void *trampoline_table;
-+ void *trampoline_table_entry;
-+#else
-+ char tramp[FFI_TRAMPOLINE_SIZE];
-+#endif
-+
-+ ffi_cif *cif;
-+
-+#if !FFI_NATIVE_RAW_API
-+
-+ /* if this is enabled, then a raw closure has the same layout
-+ as a regular closure. We use this to install an intermediate
-+ handler to do the transaltion, void** -> ffi_raw*. */
-+
-+ void (*translate_args)(ffi_cif*,void*,void**,void*);
-+ void *this_closure;
-+
-+#endif
-+
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
-+ void *user_data;
-+
-+} ffi_java_raw_closure;
-+
-+ffi_status
-+ffi_prep_raw_closure (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_raw_closure_loc (ffi_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+ffi_status
-+ffi_prep_java_raw_closure (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data);
-+
-+ffi_status
-+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data,
-+ void *codeloc);
-+
-+#endif /* FFI_CLOSURES */
-+
-+/* ---- Public interface definition -------------------------------------- */
-+
-+ffi_status ffi_prep_cif(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+ffi_status ffi_prep_cif_var(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes);
-+
-+void ffi_call(ffi_cif *cif,
-+ void (*fn)(void),
-+ void *rvalue,
-+ void **avalue);
-+
-+/* Useful for eliminating compiler warnings */
-+#define FFI_FN(f) ((void (*)(void))f)
-+
-+/* ---- Definitions shared with assembly code ---------------------------- */
-+
-+#endif
-+
-+/* If these change, update src/mips/ffitarget.h. */
-+#define FFI_TYPE_VOID 0
-+#define FFI_TYPE_INT 1
-+#define FFI_TYPE_FLOAT 2
-+#define FFI_TYPE_DOUBLE 3
-+#if 1
-+#define FFI_TYPE_LONGDOUBLE 4
-+#else
-+#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-+#endif
-+#define FFI_TYPE_UINT8 5
-+#define FFI_TYPE_SINT8 6
-+#define FFI_TYPE_UINT16 7
-+#define FFI_TYPE_SINT16 8
-+#define FFI_TYPE_UINT32 9
-+#define FFI_TYPE_SINT32 10
-+#define FFI_TYPE_UINT64 11
-+#define FFI_TYPE_SINT64 12
-+#define FFI_TYPE_STRUCT 13
-+#define FFI_TYPE_POINTER 14
-+#define FFI_TYPE_COMPLEX 15
-+
-+/* This should always refer to the last type code (for sanity checks) */
-+#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig.h modified/Modules/_ctypes/libffi_ios/include/fficonfig.h
---- orig/Modules/_ctypes/libffi_ios/include/fficonfig.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/fficonfig.h 2015-04-26 08:17:42.000000000 +0800
-@@ -0,0 +1,24 @@
-+#ifdef __arm64__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __i386__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __arm__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __x86_64__
-+
-+#include
-+
-+
-+#endif
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h modified/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h
---- orig/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,220 @@
-+#ifdef __arm64__
-+
-+/* fficonfig.h. Generated from fficonfig.h.in by configure. */
-+/* fficonfig.h.in. Generated from configure.ac by autoheader. */
-+
-+/* Define if building universal (internal helper macro) */
-+/* #undef AC_APPLE_UNIVERSAL_BUILD */
-+
-+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-+ systems. This function is required for `alloca.c' support on those systems.
-+ */
-+/* #undef CRAY_STACKSEG_END */
-+
-+/* Define to 1 if using `alloca.c'. */
-+/* #undef C_ALLOCA */
-+
-+/* Define to the flags needed for the .section .eh_frame directive. */
-+#define EH_FRAME_FLAGS "aw"
-+
-+/* Define this if you want extra debugging. */
-+/* #undef FFI_DEBUG */
-+
-+/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
-+/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
-+
-+/* Define this if you want to enable pax emulated trampolines */
-+/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
-+
-+/* Cannot use malloc on this target, so, we revert to alternative means */
-+#define FFI_MMAP_EXEC_WRIT 1
-+
-+/* Define this if you do not want support for the raw API. */
-+/* #undef FFI_NO_RAW_API */
-+
-+/* Define this if you do not want support for aggregate types. */
-+/* #undef FFI_NO_STRUCTS */
-+
-+/* Define to 1 if you have `alloca', as a function or macro. */
-+#define HAVE_ALLOCA 1
-+
-+/* Define to 1 if you have and it should be used (not on Ultrix).
-+ */
-+#define HAVE_ALLOCA_H 1
-+
-+/* Define if your assembler supports .ascii. */
-+/* #undef HAVE_AS_ASCII_PSEUDO_OP */
-+
-+/* Define if your assembler supports .cfi_* directives. */
-+#define HAVE_AS_CFI_PSEUDO_OP 1
-+
-+/* Define if your assembler supports .register. */
-+/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-+
-+/* Define if your assembler and linker support unaligned PC relative relocs.
-+ */
-+/* #undef HAVE_AS_SPARC_UA_PCREL */
-+
-+/* Define if your assembler supports .string. */
-+/* #undef HAVE_AS_STRING_PSEUDO_OP */
-+
-+/* Define if your assembler supports unwind section type. */
-+/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
-+
-+/* Define if your assembler supports PC relative relocs. */
-+/* #undef HAVE_AS_X86_PCREL */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_DLFCN_H 1
-+
-+/* Define if __attribute__((visibility("hidden"))) is supported. */
-+/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_INTTYPES_H 1
-+
-+/* Define if you have the long double type and it is bigger than a double */
-+/* #undef HAVE_LONG_DOUBLE */
-+
-+/* Define if you support more than one size of the long double type */
-+/* #undef HAVE_LONG_DOUBLE_VARIANT */
-+
-+/* Define to 1 if you have the `memcpy' function. */
-+#define HAVE_MEMCPY 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_MEMORY_H 1
-+
-+/* Define to 1 if you have the `mkostemp' function. */
-+/* #undef HAVE_MKOSTEMP */
-+
-+/* Define to 1 if you have the `mmap' function. */
-+#define HAVE_MMAP 1
-+
-+/* Define if mmap with MAP_ANON(YMOUS) works. */
-+#define HAVE_MMAP_ANON 1
-+
-+/* Define if mmap of /dev/zero works. */
-+/* #undef HAVE_MMAP_DEV_ZERO */
-+
-+/* Define if read-only mmap of a plain file works. */
-+#define HAVE_MMAP_FILE 1
-+
-+/* Define if .eh_frame sections should be read-only. */
-+/* #undef HAVE_RO_EH_FRAME */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDINT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDLIB_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRINGS_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRING_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_MMAN_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_STAT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_TYPES_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_UNISTD_H 1
-+
-+/* Define to the sub-directory in which libtool stores uninstalled libraries.
-+ */
-+#define LT_OBJDIR ".libs/"
-+
-+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-+/* #undef NO_MINUS_C_MINUS_O */
-+
-+/* Name of package */
-+#define PACKAGE "libffi"
-+
-+/* Define to the address where bug reports for this package should be sent. */
-+#define PACKAGE_BUGREPORT "http://github.com/atgreen/libffi/issues"
-+
-+/* Define to the full name of this package. */
-+#define PACKAGE_NAME "libffi"
-+
-+/* Define to the full name and version of this package. */
-+#define PACKAGE_STRING "libffi 3.2.1"
-+
-+/* Define to the one symbol short name of this package. */
-+#define PACKAGE_TARNAME "libffi"
-+
-+/* Define to the home page for this package. */
-+#define PACKAGE_URL ""
-+
-+/* Define to the version of this package. */
-+#define PACKAGE_VERSION "3.2.1"
-+
-+/* The size of `double', as computed by sizeof. */
-+#define SIZEOF_DOUBLE 8
-+
-+/* The size of `long double', as computed by sizeof. */
-+#define SIZEOF_LONG_DOUBLE 8
-+
-+/* The size of `size_t', as computed by sizeof. */
-+#define SIZEOF_SIZE_T 8
-+
-+/* If using the C implementation of alloca, define if you know the
-+ direction of stack growth for your system; otherwise it will be
-+ automatically deduced at runtime.
-+ STACK_DIRECTION > 0 => grows toward higher addresses
-+ STACK_DIRECTION < 0 => grows toward lower addresses
-+ STACK_DIRECTION = 0 => direction of growth unknown */
-+/* #undef STACK_DIRECTION */
-+
-+/* Define to 1 if you have the ANSI C header files. */
-+#define STDC_HEADERS 1
-+
-+/* Define if symbols are underscored. */
-+#define SYMBOL_UNDERSCORE 1
-+
-+/* Define this if you are using Purify and want to suppress spurious messages.
-+ */
-+/* #undef USING_PURIFY */
-+
-+/* Version number of package */
-+#define VERSION "3.2.1"
-+
-+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-+ significant byte first (like Motorola and SPARC, unlike Intel). */
-+#if defined AC_APPLE_UNIVERSAL_BUILD
-+# if defined __BIG_ENDIAN__
-+# define WORDS_BIGENDIAN 1
-+# endif
-+#else
-+# ifndef WORDS_BIGENDIAN
-+/* # undef WORDS_BIGENDIAN */
-+# endif
-+#endif
-+
-+/* Define to `unsigned int' if does not define. */
-+/* #undef size_t */
-+
-+
-+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name) .hidden name
-+#else
-+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-+#endif
-+#else
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name)
-+#else
-+#define FFI_HIDDEN
-+#endif
-+#endif
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig_armv7.h modified/Modules/_ctypes/libffi_ios/include/fficonfig_armv7.h
---- orig/Modules/_ctypes/libffi_ios/include/fficonfig_armv7.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/fficonfig_armv7.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,220 @@
-+#ifdef __arm__
-+
-+/* fficonfig.h. Generated from fficonfig.h.in by configure. */
-+/* fficonfig.h.in. Generated from configure.ac by autoheader. */
-+
-+/* Define if building universal (internal helper macro) */
-+/* #undef AC_APPLE_UNIVERSAL_BUILD */
-+
-+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-+ systems. This function is required for `alloca.c' support on those systems.
-+ */
-+/* #undef CRAY_STACKSEG_END */
-+
-+/* Define to 1 if using `alloca.c'. */
-+/* #undef C_ALLOCA */
-+
-+/* Define to the flags needed for the .section .eh_frame directive. */
-+#define EH_FRAME_FLAGS "aw"
-+
-+/* Define this if you want extra debugging. */
-+/* #undef FFI_DEBUG */
-+
-+/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
-+#define FFI_EXEC_TRAMPOLINE_TABLE 1
-+
-+/* Define this if you want to enable pax emulated trampolines */
-+/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
-+
-+/* Cannot use malloc on this target, so, we revert to alternative means */
-+/* #undef FFI_MMAP_EXEC_WRIT */
-+
-+/* Define this if you do not want support for the raw API. */
-+/* #undef FFI_NO_RAW_API */
-+
-+/* Define this if you do not want support for aggregate types. */
-+/* #undef FFI_NO_STRUCTS */
-+
-+/* Define to 1 if you have `alloca', as a function or macro. */
-+#define HAVE_ALLOCA 1
-+
-+/* Define to 1 if you have and it should be used (not on Ultrix).
-+ */
-+#define HAVE_ALLOCA_H 1
-+
-+/* Define if your assembler supports .ascii. */
-+/* #undef HAVE_AS_ASCII_PSEUDO_OP */
-+
-+/* Define if your assembler supports .cfi_* directives. */
-+#define HAVE_AS_CFI_PSEUDO_OP 1
-+
-+/* Define if your assembler supports .register. */
-+/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-+
-+/* Define if your assembler and linker support unaligned PC relative relocs.
-+ */
-+/* #undef HAVE_AS_SPARC_UA_PCREL */
-+
-+/* Define if your assembler supports .string. */
-+/* #undef HAVE_AS_STRING_PSEUDO_OP */
-+
-+/* Define if your assembler supports unwind section type. */
-+/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
-+
-+/* Define if your assembler supports PC relative relocs. */
-+/* #undef HAVE_AS_X86_PCREL */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_DLFCN_H 1
-+
-+/* Define if __attribute__((visibility("hidden"))) is supported. */
-+/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_INTTYPES_H 1
-+
-+/* Define if you have the long double type and it is bigger than a double */
-+/* #undef HAVE_LONG_DOUBLE */
-+
-+/* Define if you support more than one size of the long double type */
-+/* #undef HAVE_LONG_DOUBLE_VARIANT */
-+
-+/* Define to 1 if you have the `memcpy' function. */
-+#define HAVE_MEMCPY 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_MEMORY_H 1
-+
-+/* Define to 1 if you have the `mkostemp' function. */
-+/* #undef HAVE_MKOSTEMP */
-+
-+/* Define to 1 if you have the `mmap' function. */
-+#define HAVE_MMAP 1
-+
-+/* Define if mmap with MAP_ANON(YMOUS) works. */
-+#define HAVE_MMAP_ANON 1
-+
-+/* Define if mmap of /dev/zero works. */
-+/* #undef HAVE_MMAP_DEV_ZERO */
-+
-+/* Define if read-only mmap of a plain file works. */
-+#define HAVE_MMAP_FILE 1
-+
-+/* Define if .eh_frame sections should be read-only. */
-+/* #undef HAVE_RO_EH_FRAME */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDINT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDLIB_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRINGS_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRING_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_MMAN_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_STAT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_TYPES_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_UNISTD_H 1
-+
-+/* Define to the sub-directory in which libtool stores uninstalled libraries.
-+ */
-+#define LT_OBJDIR ".libs/"
-+
-+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-+/* #undef NO_MINUS_C_MINUS_O */
-+
-+/* Name of package */
-+#define PACKAGE "libffi"
-+
-+/* Define to the address where bug reports for this package should be sent. */
-+#define PACKAGE_BUGREPORT "http://github.com/atgreen/libffi/issues"
-+
-+/* Define to the full name of this package. */
-+#define PACKAGE_NAME "libffi"
-+
-+/* Define to the full name and version of this package. */
-+#define PACKAGE_STRING "libffi 3.2.1"
-+
-+/* Define to the one symbol short name of this package. */
-+#define PACKAGE_TARNAME "libffi"
-+
-+/* Define to the home page for this package. */
-+#define PACKAGE_URL ""
-+
-+/* Define to the version of this package. */
-+#define PACKAGE_VERSION "3.2.1"
-+
-+/* The size of `double', as computed by sizeof. */
-+#define SIZEOF_DOUBLE 8
-+
-+/* The size of `long double', as computed by sizeof. */
-+#define SIZEOF_LONG_DOUBLE 8
-+
-+/* The size of `size_t', as computed by sizeof. */
-+#define SIZEOF_SIZE_T 4
-+
-+/* If using the C implementation of alloca, define if you know the
-+ direction of stack growth for your system; otherwise it will be
-+ automatically deduced at runtime.
-+ STACK_DIRECTION > 0 => grows toward higher addresses
-+ STACK_DIRECTION < 0 => grows toward lower addresses
-+ STACK_DIRECTION = 0 => direction of growth unknown */
-+/* #undef STACK_DIRECTION */
-+
-+/* Define to 1 if you have the ANSI C header files. */
-+#define STDC_HEADERS 1
-+
-+/* Define if symbols are underscored. */
-+#define SYMBOL_UNDERSCORE 1
-+
-+/* Define this if you are using Purify and want to suppress spurious messages.
-+ */
-+/* #undef USING_PURIFY */
-+
-+/* Version number of package */
-+#define VERSION "3.2.1"
-+
-+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-+ significant byte first (like Motorola and SPARC, unlike Intel). */
-+#if defined AC_APPLE_UNIVERSAL_BUILD
-+# if defined __BIG_ENDIAN__
-+# define WORDS_BIGENDIAN 1
-+# endif
-+#else
-+# ifndef WORDS_BIGENDIAN
-+/* # undef WORDS_BIGENDIAN */
-+# endif
-+#endif
-+
-+/* Define to `unsigned int' if does not define. */
-+/* #undef size_t */
-+
-+
-+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name) .hidden name
-+#else
-+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-+#endif
-+#else
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name)
-+#else
-+#define FFI_HIDDEN
-+#endif
-+#endif
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig_i386.h modified/Modules/_ctypes/libffi_ios/include/fficonfig_i386.h
---- orig/Modules/_ctypes/libffi_ios/include/fficonfig_i386.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/fficonfig_i386.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,220 @@
-+#ifdef __i386__
-+
-+/* fficonfig.h. Generated from fficonfig.h.in by configure. */
-+/* fficonfig.h.in. Generated from configure.ac by autoheader. */
-+
-+/* Define if building universal (internal helper macro) */
-+/* #undef AC_APPLE_UNIVERSAL_BUILD */
-+
-+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-+ systems. This function is required for `alloca.c' support on those systems.
-+ */
-+/* #undef CRAY_STACKSEG_END */
-+
-+/* Define to 1 if using `alloca.c'. */
-+/* #undef C_ALLOCA */
-+
-+/* Define to the flags needed for the .section .eh_frame directive. */
-+#define EH_FRAME_FLAGS "aw"
-+
-+/* Define this if you want extra debugging. */
-+/* #undef FFI_DEBUG */
-+
-+/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
-+/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
-+
-+/* Define this if you want to enable pax emulated trampolines */
-+/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
-+
-+/* Cannot use malloc on this target, so, we revert to alternative means */
-+#define FFI_MMAP_EXEC_WRIT 1
-+
-+/* Define this if you do not want support for the raw API. */
-+/* #undef FFI_NO_RAW_API */
-+
-+/* Define this if you do not want support for aggregate types. */
-+/* #undef FFI_NO_STRUCTS */
-+
-+/* Define to 1 if you have `alloca', as a function or macro. */
-+#define HAVE_ALLOCA 1
-+
-+/* Define to 1 if you have and it should be used (not on Ultrix).
-+ */
-+#define HAVE_ALLOCA_H 1
-+
-+/* Define if your assembler supports .ascii. */
-+/* #undef HAVE_AS_ASCII_PSEUDO_OP */
-+
-+/* Define if your assembler supports .cfi_* directives. */
-+#define HAVE_AS_CFI_PSEUDO_OP 1
-+
-+/* Define if your assembler supports .register. */
-+/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-+
-+/* Define if your assembler and linker support unaligned PC relative relocs.
-+ */
-+/* #undef HAVE_AS_SPARC_UA_PCREL */
-+
-+/* Define if your assembler supports .string. */
-+/* #undef HAVE_AS_STRING_PSEUDO_OP */
-+
-+/* Define if your assembler supports unwind section type. */
-+/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
-+
-+/* Define if your assembler supports PC relative relocs. */
-+/* #undef HAVE_AS_X86_PCREL */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_DLFCN_H 1
-+
-+/* Define if __attribute__((visibility("hidden"))) is supported. */
-+/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_INTTYPES_H 1
-+
-+/* Define if you have the long double type and it is bigger than a double */
-+#define HAVE_LONG_DOUBLE 1
-+
-+/* Define if you support more than one size of the long double type */
-+/* #undef HAVE_LONG_DOUBLE_VARIANT */
-+
-+/* Define to 1 if you have the `memcpy' function. */
-+#define HAVE_MEMCPY 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_MEMORY_H 1
-+
-+/* Define to 1 if you have the `mkostemp' function. */
-+/* #undef HAVE_MKOSTEMP */
-+
-+/* Define to 1 if you have the `mmap' function. */
-+#define HAVE_MMAP 1
-+
-+/* Define if mmap with MAP_ANON(YMOUS) works. */
-+#define HAVE_MMAP_ANON 1
-+
-+/* Define if mmap of /dev/zero works. */
-+/* #undef HAVE_MMAP_DEV_ZERO */
-+
-+/* Define if read-only mmap of a plain file works. */
-+#define HAVE_MMAP_FILE 1
-+
-+/* Define if .eh_frame sections should be read-only. */
-+/* #undef HAVE_RO_EH_FRAME */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDINT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDLIB_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRINGS_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRING_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_MMAN_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_STAT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_TYPES_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_UNISTD_H 1
-+
-+/* Define to the sub-directory in which libtool stores uninstalled libraries.
-+ */
-+#define LT_OBJDIR ".libs/"
-+
-+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-+/* #undef NO_MINUS_C_MINUS_O */
-+
-+/* Name of package */
-+#define PACKAGE "libffi"
-+
-+/* Define to the address where bug reports for this package should be sent. */
-+#define PACKAGE_BUGREPORT "http://github.com/atgreen/libffi/issues"
-+
-+/* Define to the full name of this package. */
-+#define PACKAGE_NAME "libffi"
-+
-+/* Define to the full name and version of this package. */
-+#define PACKAGE_STRING "libffi 3.2.1"
-+
-+/* Define to the one symbol short name of this package. */
-+#define PACKAGE_TARNAME "libffi"
-+
-+/* Define to the home page for this package. */
-+#define PACKAGE_URL ""
-+
-+/* Define to the version of this package. */
-+#define PACKAGE_VERSION "3.2.1"
-+
-+/* The size of `double', as computed by sizeof. */
-+#define SIZEOF_DOUBLE 8
-+
-+/* The size of `long double', as computed by sizeof. */
-+#define SIZEOF_LONG_DOUBLE 16
-+
-+/* The size of `size_t', as computed by sizeof. */
-+#define SIZEOF_SIZE_T 4
-+
-+/* If using the C implementation of alloca, define if you know the
-+ direction of stack growth for your system; otherwise it will be
-+ automatically deduced at runtime.
-+ STACK_DIRECTION > 0 => grows toward higher addresses
-+ STACK_DIRECTION < 0 => grows toward lower addresses
-+ STACK_DIRECTION = 0 => direction of growth unknown */
-+/* #undef STACK_DIRECTION */
-+
-+/* Define to 1 if you have the ANSI C header files. */
-+#define STDC_HEADERS 1
-+
-+/* Define if symbols are underscored. */
-+#define SYMBOL_UNDERSCORE 1
-+
-+/* Define this if you are using Purify and want to suppress spurious messages.
-+ */
-+/* #undef USING_PURIFY */
-+
-+/* Version number of package */
-+#define VERSION "3.2.1"
-+
-+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-+ significant byte first (like Motorola and SPARC, unlike Intel). */
-+#if defined AC_APPLE_UNIVERSAL_BUILD
-+# if defined __BIG_ENDIAN__
-+# define WORDS_BIGENDIAN 1
-+# endif
-+#else
-+# ifndef WORDS_BIGENDIAN
-+/* # undef WORDS_BIGENDIAN */
-+# endif
-+#endif
-+
-+/* Define to `unsigned int' if does not define. */
-+/* #undef size_t */
-+
-+
-+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name) .hidden name
-+#else
-+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-+#endif
-+#else
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name)
-+#else
-+#define FFI_HIDDEN
-+#endif
-+#endif
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig_x86_64.h modified/Modules/_ctypes/libffi_ios/include/fficonfig_x86_64.h
---- orig/Modules/_ctypes/libffi_ios/include/fficonfig_x86_64.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/fficonfig_x86_64.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,220 @@
-+#ifdef __x86_64__
-+
-+/* fficonfig.h. Generated from fficonfig.h.in by configure. */
-+/* fficonfig.h.in. Generated from configure.ac by autoheader. */
-+
-+/* Define if building universal (internal helper macro) */
-+/* #undef AC_APPLE_UNIVERSAL_BUILD */
-+
-+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-+ systems. This function is required for `alloca.c' support on those systems.
-+ */
-+/* #undef CRAY_STACKSEG_END */
-+
-+/* Define to 1 if using `alloca.c'. */
-+/* #undef C_ALLOCA */
-+
-+/* Define to the flags needed for the .section .eh_frame directive. */
-+#define EH_FRAME_FLAGS "aw"
-+
-+/* Define this if you want extra debugging. */
-+/* #undef FFI_DEBUG */
-+
-+/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
-+/* #undef FFI_EXEC_TRAMPOLINE_TABLE */
-+
-+/* Define this if you want to enable pax emulated trampolines */
-+/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
-+
-+/* Cannot use malloc on this target, so, we revert to alternative means */
-+#define FFI_MMAP_EXEC_WRIT 1
-+
-+/* Define this if you do not want support for the raw API. */
-+/* #undef FFI_NO_RAW_API */
-+
-+/* Define this if you do not want support for aggregate types. */
-+/* #undef FFI_NO_STRUCTS */
-+
-+/* Define to 1 if you have `alloca', as a function or macro. */
-+#define HAVE_ALLOCA 1
-+
-+/* Define to 1 if you have and it should be used (not on Ultrix).
-+ */
-+#define HAVE_ALLOCA_H 1
-+
-+/* Define if your assembler supports .ascii. */
-+/* #undef HAVE_AS_ASCII_PSEUDO_OP */
-+
-+/* Define if your assembler supports .cfi_* directives. */
-+#define HAVE_AS_CFI_PSEUDO_OP 1
-+
-+/* Define if your assembler supports .register. */
-+/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-+
-+/* Define if your assembler and linker support unaligned PC relative relocs.
-+ */
-+/* #undef HAVE_AS_SPARC_UA_PCREL */
-+
-+/* Define if your assembler supports .string. */
-+/* #undef HAVE_AS_STRING_PSEUDO_OP */
-+
-+/* Define if your assembler supports unwind section type. */
-+/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
-+
-+/* Define if your assembler supports PC relative relocs. */
-+/* #undef HAVE_AS_X86_PCREL */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_DLFCN_H 1
-+
-+/* Define if __attribute__((visibility("hidden"))) is supported. */
-+/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_INTTYPES_H 1
-+
-+/* Define if you have the long double type and it is bigger than a double */
-+#define HAVE_LONG_DOUBLE 1
-+
-+/* Define if you support more than one size of the long double type */
-+/* #undef HAVE_LONG_DOUBLE_VARIANT */
-+
-+/* Define to 1 if you have the `memcpy' function. */
-+#define HAVE_MEMCPY 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_MEMORY_H 1
-+
-+/* Define to 1 if you have the `mkostemp' function. */
-+/* #undef HAVE_MKOSTEMP */
-+
-+/* Define to 1 if you have the `mmap' function. */
-+#define HAVE_MMAP 1
-+
-+/* Define if mmap with MAP_ANON(YMOUS) works. */
-+#define HAVE_MMAP_ANON 1
-+
-+/* Define if mmap of /dev/zero works. */
-+/* #undef HAVE_MMAP_DEV_ZERO */
-+
-+/* Define if read-only mmap of a plain file works. */
-+#define HAVE_MMAP_FILE 1
-+
-+/* Define if .eh_frame sections should be read-only. */
-+/* #undef HAVE_RO_EH_FRAME */
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDINT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STDLIB_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRINGS_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_STRING_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_MMAN_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_STAT_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_SYS_TYPES_H 1
-+
-+/* Define to 1 if you have the header file. */
-+#define HAVE_UNISTD_H 1
-+
-+/* Define to the sub-directory in which libtool stores uninstalled libraries.
-+ */
-+#define LT_OBJDIR ".libs/"
-+
-+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-+/* #undef NO_MINUS_C_MINUS_O */
-+
-+/* Name of package */
-+#define PACKAGE "libffi"
-+
-+/* Define to the address where bug reports for this package should be sent. */
-+#define PACKAGE_BUGREPORT "http://github.com/atgreen/libffi/issues"
-+
-+/* Define to the full name of this package. */
-+#define PACKAGE_NAME "libffi"
-+
-+/* Define to the full name and version of this package. */
-+#define PACKAGE_STRING "libffi 3.2.1"
-+
-+/* Define to the one symbol short name of this package. */
-+#define PACKAGE_TARNAME "libffi"
-+
-+/* Define to the home page for this package. */
-+#define PACKAGE_URL ""
-+
-+/* Define to the version of this package. */
-+#define PACKAGE_VERSION "3.2.1"
-+
-+/* The size of `double', as computed by sizeof. */
-+#define SIZEOF_DOUBLE 8
-+
-+/* The size of `long double', as computed by sizeof. */
-+#define SIZEOF_LONG_DOUBLE 16
-+
-+/* The size of `size_t', as computed by sizeof. */
-+#define SIZEOF_SIZE_T 8
-+
-+/* If using the C implementation of alloca, define if you know the
-+ direction of stack growth for your system; otherwise it will be
-+ automatically deduced at runtime.
-+ STACK_DIRECTION > 0 => grows toward higher addresses
-+ STACK_DIRECTION < 0 => grows toward lower addresses
-+ STACK_DIRECTION = 0 => direction of growth unknown */
-+/* #undef STACK_DIRECTION */
-+
-+/* Define to 1 if you have the ANSI C header files. */
-+#define STDC_HEADERS 1
-+
-+/* Define if symbols are underscored. */
-+#define SYMBOL_UNDERSCORE 1
-+
-+/* Define this if you are using Purify and want to suppress spurious messages.
-+ */
-+/* #undef USING_PURIFY */
-+
-+/* Version number of package */
-+#define VERSION "3.2.1"
-+
-+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-+ significant byte first (like Motorola and SPARC, unlike Intel). */
-+#if defined AC_APPLE_UNIVERSAL_BUILD
-+# if defined __BIG_ENDIAN__
-+# define WORDS_BIGENDIAN 1
-+# endif
-+#else
-+# ifndef WORDS_BIGENDIAN
-+/* # undef WORDS_BIGENDIAN */
-+# endif
-+#endif
-+
-+/* Define to `unsigned int' if does not define. */
-+/* #undef size_t */
-+
-+
-+#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name) .hidden name
-+#else
-+#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
-+#endif
-+#else
-+#ifdef LIBFFI_ASM
-+#define FFI_HIDDEN(name)
-+#else
-+#define FFI_HIDDEN
-+#endif
-+#endif
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffitarget.h modified/Modules/_ctypes/libffi_ios/include/ffitarget.h
---- orig/Modules/_ctypes/libffi_ios/include/ffitarget.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffitarget.h 2015-04-26 08:17:42.000000000 +0800
-@@ -0,0 +1,24 @@
-+#ifdef __arm64__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __i386__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __arm__
-+
-+#include
-+
-+
-+#endif
-+#ifdef __x86_64__
-+
-+#include
-+
-+
-+#endif
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffitarget_arm64.h modified/Modules/_ctypes/libffi_ios/include/ffitarget_arm64.h
---- orig/Modules/_ctypes/libffi_ios/include/ffitarget_arm64.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffitarget_arm64.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,68 @@
-+#ifdef __arm64__
-+
-+/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
-+
-+Permission is hereby granted, free of charge, to any person obtaining
-+a copy of this software and associated documentation files (the
-+``Software''), to deal in the Software without restriction, including
-+without limitation the rights to use, copy, modify, merge, publish,
-+distribute, sublicense, and/or sell copies of the Software, and to
-+permit persons to whom the Software is furnished to do so, subject to
-+the following conditions:
-+
-+The above copyright notice and this permission notice shall be
-+included in all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-+
-+#ifndef LIBFFI_TARGET_H
-+#define LIBFFI_TARGET_H
-+
-+#ifndef LIBFFI_H
-+#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
-+#endif
-+
-+#ifndef LIBFFI_ASM
-+typedef unsigned long ffi_arg;
-+typedef signed long ffi_sarg;
-+
-+typedef enum ffi_abi
-+ {
-+ FFI_FIRST_ABI = 0,
-+ FFI_SYSV,
-+ FFI_LAST_ABI,
-+ FFI_DEFAULT_ABI = FFI_SYSV
-+ } ffi_abi;
-+#endif
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#define FFI_CLOSURES 1
-+#define FFI_TRAMPOLINE_SIZE 36
-+#define FFI_NATIVE_RAW_API 0
-+
-+/* ---- Internal ---- */
-+
-+#if defined (__APPLE__)
-+#define FFI_TARGET_SPECIFIC_VARIADIC
-+#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags; unsigned aarch64_nfixedargs
-+#else
-+#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
-+#endif
-+
-+#define AARCH64_FFI_WITH_V_BIT 0
-+
-+#define AARCH64_N_XREG 32
-+#define AARCH64_N_VREG 32
-+#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
-+
-+#endif
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffitarget_armv7.h modified/Modules/_ctypes/libffi_ios/include/ffitarget_armv7.h
---- orig/Modules/_ctypes/libffi_ios/include/ffitarget_armv7.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffitarget_armv7.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,76 @@
-+#ifdef __arm__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ ffitarget.h - Copyright (c) 2012 Anthony Green
-+ Copyright (c) 2010 CodeSourcery
-+ Copyright (c) 1996-2003 Red Hat, Inc.
-+
-+ Target configuration macros for ARM.
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_TARGET_H
-+#define LIBFFI_TARGET_H
-+
-+#ifndef LIBFFI_H
-+#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
-+#endif
-+
-+#ifndef LIBFFI_ASM
-+typedef unsigned long ffi_arg;
-+typedef signed long ffi_sarg;
-+
-+typedef enum ffi_abi {
-+ FFI_FIRST_ABI = 0,
-+ FFI_SYSV,
-+ FFI_VFP,
-+ FFI_LAST_ABI,
-+#ifdef __ARM_PCS_VFP
-+ FFI_DEFAULT_ABI = FFI_VFP,
-+#else
-+ FFI_DEFAULT_ABI = FFI_SYSV,
-+#endif
-+} ffi_abi;
-+#endif
-+
-+#define FFI_EXTRA_CIF_FIELDS \
-+ int vfp_used; \
-+ short vfp_reg_free, vfp_nargs; \
-+ signed char vfp_args[16] \
-+
-+/* Internally used. */
-+#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
-+#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
-+
-+#define FFI_TARGET_SPECIFIC_VARIADIC
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#define FFI_CLOSURES 1
-+#define FFI_TRAMPOLINE_SIZE 20
-+#define FFI_NATIVE_RAW_API 0
-+
-+#endif
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffitarget_i386.h modified/Modules/_ctypes/libffi_ios/include/ffitarget_i386.h
---- orig/Modules/_ctypes/libffi_ios/include/ffitarget_i386.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffitarget_i386.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,155 @@
-+#ifdef __i386__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ ffitarget.h - Copyright (c) 2012, 2014 Anthony Green
-+ Copyright (c) 1996-2003, 2010 Red Hat, Inc.
-+ Copyright (C) 2008 Free Software Foundation, Inc.
-+
-+ Target configuration macros for x86 and x86-64.
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_TARGET_H
-+#define LIBFFI_TARGET_H
-+
-+#ifndef LIBFFI_H
-+#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
-+#endif
-+
-+/* ---- System specific configurations ----------------------------------- */
-+
-+/* For code common to all platforms on x86 and x86_64. */
-+#define X86_ANY
-+
-+#if defined (X86_64) && defined (__i386__)
-+#undef X86_64
-+#define X86
-+#endif
-+
-+#ifdef X86_WIN64
-+#define FFI_SIZEOF_ARG 8
-+#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
-+#endif
-+
-+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
-+#define FFI_TARGET_HAS_COMPLEX_TYPE
-+
-+/* ---- Generic type definitions ----------------------------------------- */
-+
-+#ifndef LIBFFI_ASM
-+#ifdef X86_WIN64
-+#ifdef _MSC_VER
-+typedef unsigned __int64 ffi_arg;
-+typedef __int64 ffi_sarg;
-+#else
-+typedef unsigned long long ffi_arg;
-+typedef long long ffi_sarg;
-+#endif
-+#else
-+#if defined __x86_64__ && defined __ILP32__
-+#define FFI_SIZEOF_ARG 8
-+#define FFI_SIZEOF_JAVA_RAW 4
-+typedef unsigned long long ffi_arg;
-+typedef long long ffi_sarg;
-+#else
-+typedef unsigned long ffi_arg;
-+typedef signed long ffi_sarg;
-+#endif
-+#endif
-+
-+typedef enum ffi_abi {
-+ FFI_FIRST_ABI = 0,
-+
-+ /* ---- Intel x86 Win32 ---------- */
-+#ifdef X86_WIN32
-+ FFI_SYSV,
-+ FFI_STDCALL,
-+ FFI_THISCALL,
-+ FFI_FASTCALL,
-+ FFI_MS_CDECL,
-+ FFI_PASCAL,
-+ FFI_REGISTER,
-+ FFI_LAST_ABI,
-+#ifdef _MSC_VER
-+ FFI_DEFAULT_ABI = FFI_MS_CDECL
-+#else
-+ FFI_DEFAULT_ABI = FFI_SYSV
-+#endif
-+
-+#elif defined(X86_WIN64)
-+ FFI_WIN64,
-+ FFI_LAST_ABI,
-+ FFI_DEFAULT_ABI = FFI_WIN64
-+
-+#else
-+ /* ---- Intel x86 and AMD x86-64 - */
-+ FFI_SYSV,
-+ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
-+ FFI_THISCALL,
-+ FFI_FASTCALL,
-+ FFI_STDCALL,
-+ FFI_PASCAL,
-+ FFI_REGISTER,
-+ FFI_LAST_ABI,
-+#if defined(__i386__) || defined(__i386)
-+ FFI_DEFAULT_ABI = FFI_SYSV
-+#else
-+ FFI_DEFAULT_ABI = FFI_UNIX64
-+#endif
-+#endif
-+} ffi_abi;
-+#endif
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#define FFI_CLOSURES 1
-+#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
-+#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
-+#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
-+#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4)
-+
-+#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
-+#define FFI_TRAMPOLINE_SIZE 24
-+#define FFI_NATIVE_RAW_API 0
-+#else
-+#ifdef X86_WIN32
-+#define FFI_TRAMPOLINE_SIZE 52
-+#else
-+#ifdef X86_WIN64
-+#define FFI_TRAMPOLINE_SIZE 29
-+#define FFI_NATIVE_RAW_API 0
-+#define FFI_NO_RAW_API 1
-+#else
-+#define FFI_TRAMPOLINE_SIZE 10
-+#endif
-+#endif
-+#ifndef X86_WIN64
-+#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
-+#endif
-+#endif
-+
-+#endif
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffitarget_x86_64.h modified/Modules/_ctypes/libffi_ios/include/ffitarget_x86_64.h
---- orig/Modules/_ctypes/libffi_ios/include/ffitarget_x86_64.h 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/include/ffitarget_x86_64.h 2015-04-26 08:18:27.000000000 +0800
-@@ -0,0 +1,155 @@
-+#ifdef __x86_64__
-+
-+/* -----------------------------------------------------------------*-C-*-
-+ ffitarget.h - Copyright (c) 2012, 2014 Anthony Green
-+ Copyright (c) 1996-2003, 2010 Red Hat, Inc.
-+ Copyright (C) 2008 Free Software Foundation, Inc.
-+
-+ Target configuration macros for x86 and x86-64.
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+
-+ ----------------------------------------------------------------------- */
-+
-+#ifndef LIBFFI_TARGET_H
-+#define LIBFFI_TARGET_H
-+
-+#ifndef LIBFFI_H
-+#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
-+#endif
-+
-+/* ---- System specific configurations ----------------------------------- */
-+
-+/* For code common to all platforms on x86 and x86_64. */
-+#define X86_ANY
-+
-+#if defined (X86_64) && defined (__i386__)
-+#undef X86_64
-+#define X86
-+#endif
-+
-+#ifdef X86_WIN64
-+#define FFI_SIZEOF_ARG 8
-+#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
-+#endif
-+
-+#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
-+#define FFI_TARGET_HAS_COMPLEX_TYPE
-+
-+/* ---- Generic type definitions ----------------------------------------- */
-+
-+#ifndef LIBFFI_ASM
-+#ifdef X86_WIN64
-+#ifdef _MSC_VER
-+typedef unsigned __int64 ffi_arg;
-+typedef __int64 ffi_sarg;
-+#else
-+typedef unsigned long long ffi_arg;
-+typedef long long ffi_sarg;
-+#endif
-+#else
-+#if defined __x86_64__ && defined __ILP32__
-+#define FFI_SIZEOF_ARG 8
-+#define FFI_SIZEOF_JAVA_RAW 4
-+typedef unsigned long long ffi_arg;
-+typedef long long ffi_sarg;
-+#else
-+typedef unsigned long ffi_arg;
-+typedef signed long ffi_sarg;
-+#endif
-+#endif
-+
-+typedef enum ffi_abi {
-+ FFI_FIRST_ABI = 0,
-+
-+ /* ---- Intel x86 Win32 ---------- */
-+#ifdef X86_WIN32
-+ FFI_SYSV,
-+ FFI_STDCALL,
-+ FFI_THISCALL,
-+ FFI_FASTCALL,
-+ FFI_MS_CDECL,
-+ FFI_PASCAL,
-+ FFI_REGISTER,
-+ FFI_LAST_ABI,
-+#ifdef _MSC_VER
-+ FFI_DEFAULT_ABI = FFI_MS_CDECL
-+#else
-+ FFI_DEFAULT_ABI = FFI_SYSV
-+#endif
-+
-+#elif defined(X86_WIN64)
-+ FFI_WIN64,
-+ FFI_LAST_ABI,
-+ FFI_DEFAULT_ABI = FFI_WIN64
-+
-+#else
-+ /* ---- Intel x86 and AMD x86-64 - */
-+ FFI_SYSV,
-+ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
-+ FFI_THISCALL,
-+ FFI_FASTCALL,
-+ FFI_STDCALL,
-+ FFI_PASCAL,
-+ FFI_REGISTER,
-+ FFI_LAST_ABI,
-+#if defined(__i386__) || defined(__i386)
-+ FFI_DEFAULT_ABI = FFI_SYSV
-+#else
-+ FFI_DEFAULT_ABI = FFI_UNIX64
-+#endif
-+#endif
-+} ffi_abi;
-+#endif
-+
-+/* ---- Definitions for closures ----------------------------------------- */
-+
-+#define FFI_CLOSURES 1
-+#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
-+#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
-+#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
-+#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4)
-+
-+#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
-+#define FFI_TRAMPOLINE_SIZE 24
-+#define FFI_NATIVE_RAW_API 0
-+#else
-+#ifdef X86_WIN32
-+#define FFI_TRAMPOLINE_SIZE 52
-+#else
-+#ifdef X86_WIN64
-+#define FFI_TRAMPOLINE_SIZE 29
-+#define FFI_NATIVE_RAW_API 0
-+#define FFI_NO_RAW_API 1
-+#else
-+#define FFI_TRAMPOLINE_SIZE 10
-+#endif
-+#endif
-+#ifndef X86_WIN64
-+#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
-+#endif
-+#endif
-+
-+#endif
-+
-+
-+
-+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/java_raw_api.c modified/Modules/_ctypes/libffi_ios/java_raw_api.c
---- orig/Modules/_ctypes/libffi_ios/java_raw_api.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/java_raw_api.c 2015-04-26 08:17:59.000000000 +0800
-@@ -0,0 +1,374 @@
-+/* -----------------------------------------------------------------------
-+ java_raw_api.c - Copyright (c) 1999, 2007, 2008 Red Hat, Inc.
-+
-+ Cloned from raw_api.c
-+
-+ Raw_api.c author: Kresten Krab Thorup
-+ Java_raw_api.c author: Hans-J. Boehm
-+
-+ $Id $
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
-+
-+/* This defines a Java- and 64-bit specific variant of the raw API. */
-+/* It assumes that "raw" argument blocks look like Java stacks on a */
-+/* 64-bit machine. Arguments that can be stored in a single stack */
-+/* stack slots (longs, doubles) occupy 128 bits, but only the first */
-+/* 64 bits are actually used. */
-+
-+#include
-+#include
-+#include
-+
-+#if !defined(NO_JAVA_RAW_API)
-+
-+size_t
-+ffi_java_raw_size (ffi_cif *cif)
-+{
-+ size_t result = 0;
-+ int i;
-+
-+ ffi_type **at = cif->arg_types;
-+
-+ for (i = cif->nargs-1; i >= 0; i--, at++)
-+ {
-+ switch((*at) -> type) {
-+ case FFI_TYPE_UINT64:
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_DOUBLE:
-+ result += 2 * FFI_SIZEOF_JAVA_RAW;
-+ break;
-+ case FFI_TYPE_STRUCT:
-+ /* No structure parameters in Java. */
-+ abort();
-+ case FFI_TYPE_COMPLEX:
-+ /* Not supported yet. */
-+ abort();
-+ default:
-+ result += FFI_SIZEOF_JAVA_RAW;
-+ }
-+ }
-+
-+ return result;
-+}
-+
-+
-+void
-+ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
-+{
-+ unsigned i;
-+ ffi_type **tp = cif->arg_types;
-+
-+#if WORDS_BIGENDIAN
-+
-+ for (i = 0; i < cif->nargs; i++, tp++, args++)
-+ {
-+ switch ((*tp)->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+ case FFI_TYPE_SINT8:
-+ *args = (void*) ((char*)(raw++) + 3);
-+ break;
-+
-+ case FFI_TYPE_UINT16:
-+ case FFI_TYPE_SINT16:
-+ *args = (void*) ((char*)(raw++) + 2);
-+ break;
-+
-+#if FFI_SIZEOF_JAVA_RAW == 8
-+ case FFI_TYPE_UINT64:
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_DOUBLE:
-+ *args = (void *)raw;
-+ raw += 2;
-+ break;
-+#endif
-+
-+ case FFI_TYPE_POINTER:
-+ *args = (void*) &(raw++)->ptr;
-+ break;
-+
-+ case FFI_TYPE_COMPLEX:
-+ /* Not supported yet. */
-+ abort();
-+
-+ default:
-+ *args = raw;
-+ raw +=
-+ ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
-+ }
-+ }
-+
-+#else /* WORDS_BIGENDIAN */
-+
-+#if !PDP
-+
-+ /* then assume little endian */
-+ for (i = 0; i < cif->nargs; i++, tp++, args++)
-+ {
-+#if FFI_SIZEOF_JAVA_RAW == 8
-+ switch((*tp)->type) {
-+ case FFI_TYPE_UINT64:
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_DOUBLE:
-+ *args = (void*) raw;
-+ raw += 2;
-+ break;
-+ case FFI_TYPE_COMPLEX:
-+ /* Not supported yet. */
-+ abort();
-+ default:
-+ *args = (void*) raw++;
-+ }
-+#else /* FFI_SIZEOF_JAVA_RAW != 8 */
-+ *args = (void*) raw;
-+ raw +=
-+ ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
-+#endif /* FFI_SIZEOF_JAVA_RAW == 8 */
-+ }
-+
-+#else
-+#error "pdp endian not supported"
-+#endif /* ! PDP */
-+
-+#endif /* WORDS_BIGENDIAN */
-+}
-+
-+void
-+ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
-+{
-+ unsigned i;
-+ ffi_type **tp = cif->arg_types;
-+
-+ for (i = 0; i < cif->nargs; i++, tp++, args++)
-+ {
-+ switch ((*tp)->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+#if WORDS_BIGENDIAN
-+ *(UINT32*)(raw++) = *(UINT8*) (*args);
-+#else
-+ (raw++)->uint = *(UINT8*) (*args);
-+#endif
-+ break;
-+
-+ case FFI_TYPE_SINT8:
-+#if WORDS_BIGENDIAN
-+ *(SINT32*)(raw++) = *(SINT8*) (*args);
-+#else
-+ (raw++)->sint = *(SINT8*) (*args);
-+#endif
-+ break;
-+
-+ case FFI_TYPE_UINT16:
-+#if WORDS_BIGENDIAN
-+ *(UINT32*)(raw++) = *(UINT16*) (*args);
-+#else
-+ (raw++)->uint = *(UINT16*) (*args);
-+#endif
-+ break;
-+
-+ case FFI_TYPE_SINT16:
-+#if WORDS_BIGENDIAN
-+ *(SINT32*)(raw++) = *(SINT16*) (*args);
-+#else
-+ (raw++)->sint = *(SINT16*) (*args);
-+#endif
-+ break;
-+
-+ case FFI_TYPE_UINT32:
-+#if WORDS_BIGENDIAN
-+ *(UINT32*)(raw++) = *(UINT32*) (*args);
-+#else
-+ (raw++)->uint = *(UINT32*) (*args);
-+#endif
-+ break;
-+
-+ case FFI_TYPE_SINT32:
-+#if WORDS_BIGENDIAN
-+ *(SINT32*)(raw++) = *(SINT32*) (*args);
-+#else
-+ (raw++)->sint = *(SINT32*) (*args);
-+#endif
-+ break;
-+
-+ case FFI_TYPE_FLOAT:
-+ (raw++)->flt = *(FLOAT32*) (*args);
-+ break;
-+
-+#if FFI_SIZEOF_JAVA_RAW == 8
-+ case FFI_TYPE_UINT64:
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_DOUBLE:
-+ raw->uint = *(UINT64*) (*args);
-+ raw += 2;
-+ break;
-+#endif
-+
-+ case FFI_TYPE_POINTER:
-+ (raw++)->ptr = **(void***) args;
-+ break;
-+
-+ default:
-+#if FFI_SIZEOF_JAVA_RAW == 8
-+ FFI_ASSERT(0); /* Should have covered all cases */
-+#else
-+ memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
-+ raw +=
-+ ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
-+#endif
-+ }
-+ }
++void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) {
++ void* mem;
++ size_t req = 0;
++ mstate ms = (mstate)msp;
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ return 0;
++ }
++ if (n_elements != 0) {
++ req = n_elements * elem_size;
++ if (((n_elements | elem_size) & ~(size_t)0xffff) &&
++ (req / n_elements != elem_size))
++ req = MAX_SIZE_T; /* force downstream failure on overflow */
++ }
++ mem = internal_malloc(ms, req);
++ if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
++ memset(mem, 0, req);
++ return mem;
+}
+
-+#if !FFI_NATIVE_RAW_API
-+
-+static void
-+ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
-+{
-+#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
-+ switch (cif->rtype->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+ case FFI_TYPE_UINT16:
-+ case FFI_TYPE_UINT32:
-+ *(UINT64 *)rvalue <<= 32;
-+ break;
-+
-+ case FFI_TYPE_SINT8:
-+ case FFI_TYPE_SINT16:
-+ case FFI_TYPE_SINT32:
-+ case FFI_TYPE_INT:
-+#if FFI_SIZEOF_JAVA_RAW == 4
-+ case FFI_TYPE_POINTER:
-+#endif
-+ *(SINT64 *)rvalue <<= 32;
-+ break;
-+
-+ case FFI_TYPE_COMPLEX:
-+ /* Not supported yet. */
-+ abort();
-+
-+ default:
-+ break;
++void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) {
++ if (oldmem == 0)
++ return mspace_malloc(msp, bytes);
++#ifdef REALLOC_ZERO_BYTES_FREES
++ if (bytes == 0) {
++ mspace_free(msp, oldmem);
++ return 0;
++ }
++#endif /* REALLOC_ZERO_BYTES_FREES */
++ else {
++#if FOOTERS
++ mchunkptr p = mem2chunk(oldmem);
++ mstate ms = get_mstate_for(p);
++#else /* FOOTERS */
++ mstate ms = (mstate)msp;
++#endif /* FOOTERS */
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ return 0;
+ }
-+#endif
++ return internal_realloc(ms, oldmem, bytes);
++ }
+}
+
-+static void
-+ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
-+{
-+#if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
-+ switch (cif->rtype->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+ case FFI_TYPE_UINT16:
-+ case FFI_TYPE_UINT32:
-+ *(UINT64 *)rvalue >>= 32;
-+ break;
++void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) {
++ mstate ms = (mstate)msp;
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ return 0;
++ }
++ return internal_memalign(ms, alignment, bytes);
++}
+
-+ case FFI_TYPE_SINT8:
-+ case FFI_TYPE_SINT16:
-+ case FFI_TYPE_SINT32:
-+ case FFI_TYPE_INT:
-+ *(SINT64 *)rvalue >>= 32;
-+ break;
++void** mspace_independent_calloc(mspace msp, size_t n_elements,
++ size_t elem_size, void* chunks[]) {
++ size_t sz = elem_size; /* serves as 1-element array */
++ mstate ms = (mstate)msp;
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ return 0;
++ }
++ return ialloc(ms, n_elements, &sz, 3, chunks);
++}
+
-+ case FFI_TYPE_COMPLEX:
-+ /* Not supported yet. */
-+ abort();
++void** mspace_independent_comalloc(mspace msp, size_t n_elements,
++ size_t sizes[], void* chunks[]) {
++ mstate ms = (mstate)msp;
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ return 0;
++ }
++ return ialloc(ms, n_elements, sizes, 0, chunks);
++}
+
-+ default:
-+ break;
++int mspace_trim(mspace msp, size_t pad) {
++ int result = 0;
++ mstate ms = (mstate)msp;
++ if (ok_magic(ms)) {
++ if (!PREACTION(ms)) {
++ result = sys_trim(ms, pad);
++ POSTACTION(ms);
+ }
-+#endif
++ }
++ else {
++ USAGE_ERROR_ACTION(ms,ms);
++ }
++ return result;
+}
+
-+/* This is a generic definition of ffi_raw_call, to be used if the
-+ * native system does not provide a machine-specific implementation.
-+ * Having this, allows code to be written for the raw API, without
-+ * the need for system-specific code to handle input in that format;
-+ * these following couple of functions will handle the translation forth
-+ * and back automatically. */
-+
-+void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
-+ ffi_java_raw *raw)
-+{
-+ void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
-+ ffi_java_raw_to_ptrarray (cif, raw, avalue);
-+ ffi_call (cif, fn, rvalue, avalue);
-+ ffi_java_rvalue_to_raw (cif, rvalue);
++void mspace_malloc_stats(mspace msp) {
++ mstate ms = (mstate)msp;
++ if (ok_magic(ms)) {
++ internal_malloc_stats(ms);
++ }
++ else {
++ USAGE_ERROR_ACTION(ms,ms);
++ }
+}
+
-+#if FFI_CLOSURES /* base system provides closures */
-+
-+static void
-+ffi_java_translate_args (ffi_cif *cif, void *rvalue,
-+ void **avalue, void *user_data)
-+{
-+ ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
-+ ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
-+
-+ ffi_java_ptrarray_to_raw (cif, avalue, raw);
-+ (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
-+ ffi_java_raw_to_rvalue (cif, rvalue);
++size_t mspace_footprint(mspace msp) {
++ size_t result;
++ mstate ms = (mstate)msp;
++ if (ok_magic(ms)) {
++ result = ms->footprint;
++ }
++ USAGE_ERROR_ACTION(ms,ms);
++ return result;
+}
+
-+ffi_status
-+ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data,
-+ void *codeloc)
-+{
-+ ffi_status status;
-+
-+ status = ffi_prep_closure_loc ((ffi_closure*) cl,
-+ cif,
-+ &ffi_java_translate_args,
-+ codeloc,
-+ codeloc);
-+ if (status == FFI_OK)
-+ {
-+ cl->fun = fun;
-+ cl->user_data = user_data;
-+ }
+
-+ return status;
++size_t mspace_max_footprint(mspace msp) {
++ size_t result;
++ mstate ms = (mstate)msp;
++ if (ok_magic(ms)) {
++ result = ms->max_footprint;
++ }
++ USAGE_ERROR_ACTION(ms,ms);
++ return result;
+}
+
-+/* Again, here is the generic version of ffi_prep_raw_closure, which
-+ * will install an intermediate "hub" for translation of arguments from
-+ * the pointer-array format, to the raw format */
+
-+ffi_status
-+ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
-+ void *user_data)
-+{
-+ return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
++#if !NO_MALLINFO
++struct mallinfo mspace_mallinfo(mspace msp) {
++ mstate ms = (mstate)msp;
++ if (!ok_magic(ms)) {
++ USAGE_ERROR_ACTION(ms,ms);
++ }
++ return internal_mallinfo(ms);
+}
++#endif /* NO_MALLINFO */
+
-+#endif /* FFI_CLOSURES */
-+#endif /* !FFI_NATIVE_RAW_API */
-+#endif /* !NO_JAVA_RAW_API */
-diff -Nru orig/Modules/_ctypes/libffi_ios/prep_cif.c modified/Modules/_ctypes/libffi_ios/prep_cif.c
---- orig/Modules/_ctypes/libffi_ios/prep_cif.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/prep_cif.c 2015-04-26 08:17:59.000000000 +0800
-@@ -0,0 +1,253 @@
-+/* -----------------------------------------------------------------------
-+ prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
-+ Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
++int mspace_mallopt(int param_number, int value) {
++ return change_mparam(param_number, value);
++}
+
-+#include
-+#include
-+#include
++#endif /* MSPACES */
+
-+/* Round up to FFI_SIZEOF_ARG. */
++/* -------------------- Alternative MORECORE functions ------------------- */
+
-+#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
++/*
++ Guidelines for creating a custom version of MORECORE:
+
-+/* Perform machine independent initialization of aggregate type
-+ specifications. */
++ * For best performance, MORECORE should allocate in multiples of pagesize.
++ * MORECORE may allocate more memory than requested. (Or even less,
++ but this will usually result in a malloc failure.)
++ * MORECORE must not allocate memory when given argument zero, but
++ instead return one past the end address of memory from previous
++ nonzero call.
++ * For best performance, consecutive calls to MORECORE with positive
++ arguments should return increasing addresses, indicating that
++ space has been contiguously extended.
++ * Even though consecutive calls to MORECORE need not return contiguous
++ addresses, it must be OK for malloc'ed chunks to span multiple
++ regions in those cases where they do happen to be contiguous.
++ * MORECORE need not handle negative arguments -- it may instead
++ just return MFAIL when given negative arguments.
++ Negative arguments are always multiples of pagesize. MORECORE
++ must not misinterpret negative args as large positive unsigned
++ args. You can suppress all such calls from even occurring by defining
++ MORECORE_CANNOT_TRIM,
+
-+static ffi_status initialize_aggregate(ffi_type *arg)
-+{
-+ ffi_type **ptr;
++ As an example alternative MORECORE, here is a custom allocator
++ kindly contributed for pre-OSX macOS. It uses virtually but not
++ necessarily physically contiguous non-paged memory (locked in,
++ present and won't get swapped out). You can use it by uncommenting
++ this section, adding some #includes, and setting up the appropriate
++ defines above:
+
-+ if (UNLIKELY(arg == NULL || arg->elements == NULL))
-+ return FFI_BAD_TYPEDEF;
++ #define MORECORE osMoreCore
+
-+ arg->size = 0;
-+ arg->alignment = 0;
++ There is also a shutdown routine that should somehow be called for
++ cleanup upon program exit.
+
-+ ptr = &(arg->elements[0]);
++ #define MAX_POOL_ENTRIES 100
++ #define MINIMUM_MORECORE_SIZE (64 * 1024U)
++ static int next_os_pool;
++ void *our_os_pools[MAX_POOL_ENTRIES];
+
-+ if (UNLIKELY(ptr == 0))
-+ return FFI_BAD_TYPEDEF;
++ void *osMoreCore(int size)
++ {
++ void *ptr = 0;
++ static void *sbrk_top = 0;
+
-+ while ((*ptr) != NULL)
++ if (size > 0)
++ {
++ if (size < MINIMUM_MORECORE_SIZE)
++ size = MINIMUM_MORECORE_SIZE;
++ if (CurrentExecutionLevel() == kTaskLevel)
++ ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0);
++ if (ptr == 0)
++ {
++ return (void *) MFAIL;
++ }
++ // save ptrs so they can be freed during cleanup
++ our_os_pools[next_os_pool] = ptr;
++ next_os_pool++;
++ ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK);
++ sbrk_top = (char *) ptr + size;
++ return ptr;
++ }
++ else if (size < 0)
+ {
-+ if (UNLIKELY(((*ptr)->size == 0)
-+ && (initialize_aggregate((*ptr)) != FFI_OK)))
-+ return FFI_BAD_TYPEDEF;
++ // we don't currently support shrink behavior
++ return (void *) MFAIL;
++ }
++ else
++ {
++ return sbrk_top;
++ }
++ }
+
-+ /* Perform a sanity check on the argument type */
-+ FFI_ASSERT_VALID_TYPE(*ptr);
++ // cleanup any allocated memory pools
++ // called as last thing before shutting down driver
+
-+ arg->size = ALIGN(arg->size, (*ptr)->alignment);
-+ arg->size += (*ptr)->size;
++ void osCleanupMem(void)
++ {
++ void **ptr;
+
-+ arg->alignment = (arg->alignment > (*ptr)->alignment) ?
-+ arg->alignment : (*ptr)->alignment;
++ for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++)
++ if (*ptr)
++ {
++ PoolDeallocate(*ptr);
++ *ptr = 0;
++ }
++ }
+
-+ ptr++;
-+ }
++*/
+
-+ /* Structure size includes tail padding. This is important for
-+ structures that fit in one register on ABIs like the PowerPC64
-+ Linux ABI that right justify small structs in a register.
-+ It's also needed for nested structure layout, for example
-+ struct A { long a; char b; }; struct B { struct A x; char y; };
-+ should find y at an offset of 2*sizeof(long) and result in a
-+ total size of 3*sizeof(long). */
-+ arg->size = ALIGN (arg->size, arg->alignment);
+
-+ /* On some targets, the ABI defines that structures have an additional
-+ alignment beyond the "natural" one based on their elements. */
-+#ifdef FFI_AGGREGATE_ALIGNMENT
-+ if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
-+ arg->alignment = FFI_AGGREGATE_ALIGNMENT;
-+#endif
++/* -----------------------------------------------------------------------
++History:
++ V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee)
++ * Add max_footprint functions
++ * Ensure all appropriate literals are size_t
++ * Fix conditional compilation problem for some #define settings
++ * Avoid concatenating segments with the one provided
++ in create_mspace_with_base
++ * Rename some variables to avoid compiler shadowing warnings
++ * Use explicit lock initialization.
++ * Better handling of sbrk interference.
++ * Simplify and fix segment insertion, trimming and mspace_destroy
++ * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x
++ * Thanks especially to Dennis Flanagan for help on these.
+
-+ if (arg->size == 0)
-+ return FFI_BAD_TYPEDEF;
-+ else
-+ return FFI_OK;
-+}
++ V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee)
++ * Fix memalign brace error.
+
-+#ifndef __CRIS__
-+/* The CRIS ABI specifies structure elements to have byte
-+ alignment only, so it completely overrides this functions,
-+ which assumes "natural" alignment and padding. */
++ V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee)
++ * Fix improper #endif nesting in C++
++ * Add explicit casts needed for C++
+
-+/* Perform machine independent ffi_cif preparation, then call
-+ machine dependent routine. */
++ V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee)
++ * Use trees for large bins
++ * Support mspaces
++ * Use segments to unify sbrk-based and mmap-based system allocation,
++ removing need for emulation on most platforms without sbrk.
++ * Default safety checks
++ * Optional footer checks. Thanks to William Robertson for the idea.
++ * Internal code refactoring
++ * Incorporate suggestions and platform-specific changes.
++ Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas,
++ Aaron Bachmann, Emery Berger, and others.
++ * Speed up non-fastbin processing enough to remove fastbins.
++ * Remove useless cfree() to avoid conflicts with other apps.
++ * Remove internal memcpy, memset. Compilers handle builtins better.
++ * Remove some options that no one ever used and rename others.
+
-+/* For non variadic functions isvariadic should be 0 and
-+ nfixedargs==ntotalargs.
++ V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
++ * Fix malloc_state bitmap array misdeclaration
+
-+ For variadic calls, isvariadic should be 1 and nfixedargs
-+ and ntotalargs set as appropriate. nfixedargs must always be >=1 */
++ V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee)
++ * Allow tuning of FIRST_SORTED_BIN_SIZE
++ * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte.
++ * Better detection and support for non-contiguousness of MORECORE.
++ Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger
++ * Bypass most of malloc if no frees. Thanks To Emery Berger.
++ * Fix freeing of old top non-contiguous chunk im sysmalloc.
++ * Raised default trim and map thresholds to 256K.
++ * Fix mmap-related #defines. Thanks to Lubos Lunak.
++ * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield.
++ * Branch-free bin calculation
++ * Default trim and mmap thresholds now 256K.
+
++ V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee)
++ * Introduce independent_comalloc and independent_calloc.
++ Thanks to Michael Pachos for motivation and help.
++ * Make optional .h file available
++ * Allow > 2GB requests on 32bit systems.
++ * new WIN32 sbrk, mmap, munmap, lock code from .
++ Thanks also to Andreas Mueller ,
++ and Anonymous.
++ * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for
++ helping test this.)
++ * memalign: check alignment arg
++ * realloc: don't try to shift chunks backwards, since this
++ leads to more fragmentation in some programs and doesn't
++ seem to help in any others.
++ * Collect all cases in malloc requiring system memory into sysmalloc
++ * Use mmap as backup to sbrk
++ * Place all internal state in malloc_state
++ * Introduce fastbins (although similar to 2.5.1)
++ * Many minor tunings and cosmetic improvements
++ * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK
++ * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS
++ Thanks to Tony E. Bennett and others.
++ * Include errno.h to support default failure action.
+
-+ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
-+ unsigned int isvariadic,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype, ffi_type **atypes)
-+{
-+ unsigned bytes = 0;
-+ unsigned int i;
-+ ffi_type **ptr;
++ V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee)
++ * return null for negative arguments
++ * Added Several WIN32 cleanups from Martin C. Fong
++ * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
++ (e.g. WIN32 platforms)
++ * Cleanup header file inclusion for WIN32 platforms
++ * Cleanup code to avoid Microsoft Visual C++ compiler complaints
++ * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
++ memory allocation routines
++ * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
++ * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
++ usage of 'assert' in non-WIN32 code
++ * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
++ avoid infinite loop
++ * Always call 'fREe()' rather than 'free()'
+
-+ FFI_ASSERT(cif != NULL);
-+ FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
-+ FFI_ASSERT(nfixedargs <= ntotalargs);
++ V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee)
++ * Fixed ordering problem with boundary-stamping
+
-+ if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
-+ return FFI_BAD_ABI;
++ V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee)
++ * Added pvalloc, as recommended by H.J. Liu
++ * Added 64bit pointer support mainly from Wolfram Gloger
++ * Added anonymously donated WIN32 sbrk emulation
++ * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
++ * malloc_extend_top: fix mask error that caused wastage after
++ foreign sbrks
++ * Add linux mremap support code from HJ Liu
+
-+ cif->abi = abi;
-+ cif->arg_types = atypes;
-+ cif->nargs = ntotalargs;
-+ cif->rtype = rtype;
++ V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee)
++ * Integrated most documentation with the code.
++ * Add support for mmap, with help from
++ Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
++ * Use last_remainder in more cases.
++ * Pack bins using idea from colin@nyx10.cs.du.edu
++ * Use ordered bins instead of best-fit threshold
++ * Eliminate block-local decls to simplify tracing and debugging.
++ * Support another case of realloc via move into top
++ * Fix error occurring when initial sbrk_base not word-aligned.
++ * Rely on page size for units instead of SBRK_UNIT to
++ avoid surprises about sbrk alignment conventions.
++ * Add mallinfo, mallopt. Thanks to Raymond Nijssen
++ (raymond@es.ele.tue.nl) for the suggestion.
++ * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
++ * More precautions for cases where other routines call sbrk,
++ courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
++ * Added macros etc., allowing use in linux libc from
++ H.J. Lu (hjl@gnu.ai.mit.edu)
++ * Inverted this history list
+
-+ cif->flags = 0;
++ V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee)
++ * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
++ * Removed all preallocation code since under current scheme
++ the work required to undo bad preallocations exceeds
++ the work saved in good cases for most test programs.
++ * No longer use return list or unconsolidated bins since
++ no scheme using them consistently outperforms those that don't
++ given above changes.
++ * Use best fit for very large chunks to prevent some worst-cases.
++ * Added some support for debugging
+
-+#if HAVE_LONG_DOUBLE_VARIANT
-+ ffi_prep_types (abi);
-+#endif
++ V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee)
++ * Removed footers when chunks are in use. Thanks to
++ Paul Wilson (wilson@cs.texas.edu) for the suggestion.
+
-+ /* Initialize the return type if necessary */
-+ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
-+ return FFI_BAD_TYPEDEF;
++ V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee)
++ * Added malloc_trim, with help from Wolfram Gloger
++ (wmglo@Dent.MED.Uni-Muenchen.DE).
+
-+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
-+ if (rtype->type == FFI_TYPE_COMPLEX)
-+ abort();
-+#endif
-+ /* Perform a sanity check on the return type */
-+ FFI_ASSERT_VALID_TYPE(cif->rtype);
++ V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
+
-+ /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
-+#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
-+ /* Make space for the return structure pointer */
-+ if (cif->rtype->type == FFI_TYPE_STRUCT
-+#ifdef SPARC
-+ && (cif->abi != FFI_V9 || cif->rtype->size > 32)
-+#endif
-+#ifdef TILE
-+ && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
-+#endif
-+#ifdef XTENSA
-+ && (cif->rtype->size > 16)
-+#endif
-+#ifdef NIOS2
-+ && (cif->rtype->size > 8)
-+#endif
-+ )
-+ bytes = STACK_ARG_SIZE(sizeof(void*));
-+#endif
++ V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
++ * realloc: try to expand in both directions
++ * malloc: swap order of clean-bin strategy;
++ * realloc: only conditionally expand backwards
++ * Try not to scavenge used bins
++ * Use bin counts as a guide to preallocation
++ * Occasionally bin return list chunks in first scan
++ * Add a few optimizations from colin@nyx10.cs.du.edu
+
-+ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
-+ {
++ V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
++ * faster bin computation & slightly different binning
++ * merged all consolidations to one part of malloc proper
++ (eliminating old malloc_find_space & malloc_clean_bin)
++ * Scan 2 returns chunks (not just 1)
++ * Propagate failure in realloc if malloc returns 0
++ * Add stuff to allow compilation on non-ANSI compilers
++ from kpv@research.att.com
+
-+ /* Initialize any uninitialized aggregate type definitions */
-+ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
-+ return FFI_BAD_TYPEDEF;
++ V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
++ * removed potential for odd address access in prev_chunk
++ * removed dependency on getpagesize.h
++ * misc cosmetics and a bit more internal documentation
++ * anticosmetics: mangled names in macros to evade debugger strangeness
++ * tested on sparc, hp-700, dec-mips, rs6000
++ with gcc & native cc (hp, dec only) allowing
++ Detlefs & Zorn comparison study (in SIGPLAN Notices.)
+
-+#ifndef FFI_TARGET_HAS_COMPLEX_TYPE
-+ if ((*ptr)->type == FFI_TYPE_COMPLEX)
-+ abort();
-+#endif
-+ /* Perform a sanity check on the argument type, do this
-+ check after the initialization. */
-+ FFI_ASSERT_VALID_TYPE(*ptr);
++ Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
++ * Based loosely on libg++-1.2X malloc. (It retains some of the overall
++ structure of old version, but most details differ.)
++
++*/
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi.h modified/Modules/_ctypes/libffi_ios/include/ffi.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi.h 2015-12-20 18:55:19.000000000 +0800
+@@ -0,0 +1,24 @@
++#ifdef __arm64__
+
-+#if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
-+#ifdef SPARC
-+ if (((*ptr)->type == FFI_TYPE_STRUCT
-+ && ((*ptr)->size > 16 || cif->abi != FFI_V9))
-+ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
-+ && cif->abi != FFI_V9))
-+ bytes += sizeof(void*);
-+ else
-+#endif
-+ {
-+ /* Add any padding if necessary */
-+ if (((*ptr)->alignment - 1) & bytes)
-+ bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment);
++#include
+
-+#ifdef TILE
-+ if (bytes < 10 * FFI_SIZEOF_ARG &&
-+ bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
-+ {
-+ /* An argument is never split between the 10 parameter
-+ registers and the stack. */
-+ bytes = 10 * FFI_SIZEOF_ARG;
-+ }
-+#endif
-+#ifdef XTENSA
-+ if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
-+ bytes = 6*4;
-+#endif
+
-+ bytes += STACK_ARG_SIZE((*ptr)->size);
-+ }
+#endif
-+ }
++#ifdef __i386__
++
++#include
+
-+ cif->bytes = bytes;
+
-+ /* Perform machine dependent cif processing */
-+#ifdef FFI_TARGET_SPECIFIC_VARIADIC
-+ if (isvariadic)
-+ return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
+#endif
++#ifdef __arm__
+
-+ return ffi_prep_cif_machdep(cif);
-+}
-+#endif /* not __CRIS__ */
++#include
+
-+ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
-+ ffi_type *rtype, ffi_type **atypes)
-+{
-+ return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
-+}
+
-+ffi_status ffi_prep_cif_var(ffi_cif *cif,
-+ ffi_abi abi,
-+ unsigned int nfixedargs,
-+ unsigned int ntotalargs,
-+ ffi_type *rtype,
-+ ffi_type **atypes)
-+{
-+ return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
-+}
++#endif
++#ifdef __x86_64__
+
-+#if FFI_CLOSURES
++#include
+
-+ffi_status
-+ffi_prep_closure (ffi_closure* closure,
-+ ffi_cif* cif,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data)
-+{
-+ return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
-+}
+
+#endif
-diff -Nru orig/Modules/_ctypes/libffi_ios/raw_api.c modified/Modules/_ctypes/libffi_ios/raw_api.c
---- orig/Modules/_ctypes/libffi_ios/raw_api.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/raw_api.c 2015-04-26 08:17:59.000000000 +0800
-@@ -0,0 +1,267 @@
-+/* -----------------------------------------------------------------------
-+ raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_arm64.h modified/Modules/_ctypes/libffi_ios/include/ffi_arm64.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi_arm64.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi_arm64.h 2015-12-20 18:55:29.000000000 +0800
+@@ -0,0 +1,508 @@
++#ifdef __arm64__
+
-+ Author: Kresten Krab Thorup
++/* -----------------------------------------------------------------*-C-*-
++ libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green
++ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation
++ files (the ``Software''), to deal in the Software without
++ restriction, including without limitation the rights to use, copy,
++ modify, merge, publish, distribute, sublicense, and/or sell copies
++ of the Software, and to permit persons to whom the Software is
++ furnished to do so, subject to the following conditions:
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
@@ -30120,697 +23031,510 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/raw_api.c modified/Modules/_ctypes/lib
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
++
+ ----------------------------------------------------------------------- */
+
-+/* This file defines generic functions for use with the raw api. */
++/* -------------------------------------------------------------------
++ The basic API is described in the README file.
+
-+#include
-+#include
++ The raw API is designed to bypass some of the argument packing
++ and unpacking on architectures for which it can be avoided.
+
-+#if !FFI_NO_RAW_API
++ The closure API allows interpreted functions to be packaged up
++ inside a C function pointer, so that they can be called as C functions,
++ with no understanding on the client side that they are interpreted.
++ It can also be used in other cases in which it is necessary to package
++ up a user specified parameter and a function pointer as a single
++ function pointer.
+
-+size_t
-+ffi_raw_size (ffi_cif *cif)
-+{
-+ size_t result = 0;
-+ int i;
++ The closure API must be implemented in order to get its functionality,
++ e.g. for use by gij. Routines are provided to emulate the raw API
++ if the underlying platform doesn't allow faster implementation.
+
-+ ffi_type **at = cif->arg_types;
++ More details on the raw and cloure API can be found in:
+
-+ for (i = cif->nargs-1; i >= 0; i--, at++)
-+ {
-+#if !FFI_NO_STRUCTS
-+ if ((*at)->type == FFI_TYPE_STRUCT)
-+ result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
-+ else
-+#endif
-+ result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
-+ }
++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
-+ return result;
-+}
++ and
+
++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
++ -------------------------------------------------------------------- */
+
-+void
-+ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
-+{
-+ unsigned i;
-+ ffi_type **tp = cif->arg_types;
++#ifndef LIBFFI_H
++#define LIBFFI_H
+
-+#if WORDS_BIGENDIAN
++#ifdef __cplusplus
++extern "C" {
++#endif
+
-+ for (i = 0; i < cif->nargs; i++, tp++, args++)
-+ {
-+ switch ((*tp)->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+ case FFI_TYPE_SINT8:
-+ *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
-+ break;
-+
-+ case FFI_TYPE_UINT16:
-+ case FFI_TYPE_SINT16:
-+ *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
-+ break;
++/* Specify which architecture libffi is configured for. */
++#ifndef AARCH64
++#define AARCH64
++#endif
+
-+#if FFI_SIZEOF_ARG >= 4
-+ case FFI_TYPE_UINT32:
-+ case FFI_TYPE_SINT32:
-+ *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
-+ break;
++/* ---- System configuration information --------------------------------- */
++
++#include
++
++#ifndef LIBFFI_ASM
++
++#if defined(_MSC_VER) && !defined(__clang__)
++#define __attribute__(X)
+#endif
-+
-+#if !FFI_NO_STRUCTS
-+ case FFI_TYPE_STRUCT:
-+ *args = (raw++)->ptr;
-+ break;
++
++#include
++#include
++
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
++
++#define FFI_64_BIT_MAX 9223372036854775807
++
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif /* _AIX52 or newer */
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
++# ifndef __PPC64__
++# if defined (__IBMC__) || defined (__IBMCPP__)
++# define FFI_LONG_LONG_MAX LONGLONG_MAX
++# endif
++# endif /* __PPC64__ */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif
++# endif
+#endif
+
-+ case FFI_TYPE_COMPLEX:
-+ *args = (raw++)->ptr;
-+ break;
-+
-+ case FFI_TYPE_POINTER:
-+ *args = (void*) &(raw++)->ptr;
-+ break;
-+
-+ default:
-+ *args = raw;
-+ raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-+ }
-+ }
-+
-+#else /* WORDS_BIGENDIAN */
++/* The closure code assumes that this works on pointers, i.e. a size_t */
++/* can hold a pointer. */
+
-+#if !PDP
++typedef struct _ffi_type
++{
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++ struct _ffi_type **elements;
++} ffi_type;
+
-+ /* then assume little endian */
-+ for (i = 0; i < cif->nargs; i++, tp++, args++)
-+ {
-+#if !FFI_NO_STRUCTS
-+ if ((*tp)->type == FFI_TYPE_STRUCT)
-+ {
-+ *args = (raw++)->ptr;
-+ }
-+ else
++#ifndef LIBFFI_HIDE_BASIC_TYPES
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++ #error "char size not supported"
+#endif
-+ if ((*tp)->type == FFI_TYPE_COMPLEX)
-+ {
-+ *args = (raw++)->ptr;
-+ }
-+ else
-+ {
-+ *args = (void*) raw;
-+ raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
-+ }
-+ }
+
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
+#else
-+#error "pdp endian not supported"
-+#endif /* ! PDP */
-+
-+#endif /* WORDS_BIGENDIAN */
-+}
-+
-+void
-+ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
-+{
-+ unsigned i;
-+ ffi_type **tp = cif->arg_types;
++ #error "short size not supported"
++#endif
+
-+ for (i = 0; i < cif->nargs; i++, tp++, args++)
-+ {
-+ switch ((*tp)->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+ (raw++)->uint = *(UINT8*) (*args);
-+ break;
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++ #error "int size not supported"
++#endif
+
-+ case FFI_TYPE_SINT8:
-+ (raw++)->sint = *(SINT8*) (*args);
-+ break;
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
++ #error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != FFI_64_BIT_MAX
++ #error "long size not supported"
++#endif
+
-+ case FFI_TYPE_UINT16:
-+ (raw++)->uint = *(UINT16*) (*args);
-+ break;
++#if LONG_MAX == 2147483647
++# define ffi_type_ulong ffi_type_uint32
++# define ffi_type_slong ffi_type_sint32
++#elif LONG_MAX == FFI_64_BIT_MAX
++# define ffi_type_ulong ffi_type_uint64
++# define ffi_type_slong ffi_type_sint64
++#else
++ #error "long size not supported"
++#endif
+
-+ case FFI_TYPE_SINT16:
-+ (raw++)->sint = *(SINT16*) (*args);
-+ break;
++/* Need minimal decorations for DLLs to works on Windows. */
++/* GCC has autoimport and autoexport. Rely on Libtool to */
++/* help MSVC export from a DLL, but always declare data */
++/* to be imported for MSVC clients. This costs an extra */
++/* indirection for MSVC clients using the static version */
++/* of the library, but don't worry about that. Besides, */
++/* as a workaround, they can define FFI_BUILDING if they */
++/* *know* they are going to link with the static library. */
++#if defined _MSC_VER && !defined FFI_BUILDING
++#define FFI_EXTERN extern __declspec(dllimport)
++#else
++#define FFI_EXTERN extern
++#endif
+
-+#if FFI_SIZEOF_ARG >= 4
-+ case FFI_TYPE_UINT32:
-+ (raw++)->uint = *(UINT32*) (*args);
-+ break;
++/* These are defined in types.c */
++FFI_EXTERN ffi_type ffi_type_void;
++FFI_EXTERN ffi_type ffi_type_uint8;
++FFI_EXTERN ffi_type ffi_type_sint8;
++FFI_EXTERN ffi_type ffi_type_uint16;
++FFI_EXTERN ffi_type ffi_type_sint16;
++FFI_EXTERN ffi_type ffi_type_uint32;
++FFI_EXTERN ffi_type ffi_type_sint32;
++FFI_EXTERN ffi_type ffi_type_uint64;
++FFI_EXTERN ffi_type ffi_type_sint64;
++FFI_EXTERN ffi_type ffi_type_float;
++FFI_EXTERN ffi_type ffi_type_double;
++FFI_EXTERN ffi_type ffi_type_pointer;
+
-+ case FFI_TYPE_SINT32:
-+ (raw++)->sint = *(SINT32*) (*args);
-+ break;
++#if 0
++FFI_EXTERN ffi_type ffi_type_longdouble;
++#else
++#define ffi_type_longdouble ffi_type_double
+#endif
+
-+#if !FFI_NO_STRUCTS
-+ case FFI_TYPE_STRUCT:
-+ (raw++)->ptr = *args;
-+ break;
++#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
++FFI_EXTERN ffi_type ffi_type_complex_float;
++FFI_EXTERN ffi_type ffi_type_complex_double;
++#if 0
++FFI_EXTERN ffi_type ffi_type_complex_longdouble;
++#else
++#define ffi_type_complex_longdouble ffi_type_complex_double
++#endif
+#endif
++#endif /* LIBFFI_HIDE_BASIC_TYPES */
+
-+ case FFI_TYPE_COMPLEX:
-+ (raw++)->ptr = *args;
-+ break;
++typedef enum {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
+
-+ case FFI_TYPE_POINTER:
-+ (raw++)->ptr = **(void***) args;
-+ break;
++typedef unsigned FFI_TYPE;
+
-+ default:
-+ memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
-+ raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
-+ }
-+ }
-+}
++typedef struct {
++ ffi_abi abi;
++ unsigned nargs;
++ ffi_type **arg_types;
++ ffi_type *rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
+
-+#if !FFI_NATIVE_RAW_API
++#if 0
++/* Used to adjust size/alignment of ffi types. */
++void ffi_prep_types (ffi_abi abi);
++#endif
+
++/* Used internally, but overridden by some architectures */
++ffi_status ffi_prep_cif_core(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int isvariadic,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+/* This is a generic definition of ffi_raw_call, to be used if the
-+ * native system does not provide a machine-specific implementation.
-+ * Having this, allows code to be written for the raw API, without
-+ * the need for system-specific code to handle input in that format;
-+ * these following couple of functions will handle the translation forth
-+ * and back automatically. */
++/* ---- Definitions for the raw API -------------------------------------- */
+
-+void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
-+{
-+ void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
-+ ffi_raw_to_ptrarray (cif, raw, avalue);
-+ ffi_call (cif, fn, rvalue, avalue);
-+}
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == FFI_64_BIT_MAX
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
+
-+#if FFI_CLOSURES /* base system provides closures */
++#ifndef FFI_SIZEOF_JAVA_RAW
++# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
++#endif
+
-+static void
-+ffi_translate_args (ffi_cif *cif, void *rvalue,
-+ void **avalue, void *user_data)
-+{
-+ ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
-+ ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
++
++#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
++/* This is a special case for mips64/n32 ABI (and perhaps others) where
++ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
++typedef union {
++ signed int sint;
++ unsigned int uint;
++ float flt;
++ char data[FFI_SIZEOF_JAVA_RAW];
++ void* ptr;
++} ffi_java_raw;
++#else
++typedef ffi_raw ffi_java_raw;
++#endif
+
-+ ffi_ptrarray_to_raw (cif, avalue, raw);
-+ (*cl->fun) (cif, rvalue, raw, cl->user_data);
-+}
+
-+ffi_status
-+ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data,
-+ void *codeloc)
-+{
-+ ffi_status status;
++void ffi_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_raw *avalue);
+
-+ status = ffi_prep_closure_loc ((ffi_closure*) cl,
-+ cif,
-+ &ffi_translate_args,
-+ codeloc,
-+ codeloc);
-+ if (status == FFI_OK)
-+ {
-+ cl->fun = fun;
-+ cl->user_data = user_data;
-+ }
++void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
++void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
++size_t ffi_raw_size (ffi_cif *cif);
+
-+ return status;
-+}
++/* This is analogous to the raw API, except it uses Java parameter */
++/* packing, even on 64-bit machines. I.e. on 64-bit machines */
++/* longs and doubles are followed by an empty 64-bit word. */
+
-+#endif /* FFI_CLOSURES */
-+#endif /* !FFI_NATIVE_RAW_API */
++void ffi_java_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_java_raw *avalue);
++
++void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
++void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
++size_t ffi_java_raw_size (ffi_cif *cif);
++
++/* ---- Definitions for closures ----------------------------------------- */
+
+#if FFI_CLOSURES
+
-+/* Again, here is the generic version of ffi_prep_raw_closure, which
-+ * will install an intermediate "hub" for translation of arguments from
-+ * the pointer-array format, to the raw format */
++#ifdef _MSC_VER
++__declspec(align(8))
++#endif
++typedef struct {
++#if 1
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void *user_data;
++#ifdef __GNUC__
++} ffi_closure __attribute__((aligned (8)));
++#else
++} ffi_closure;
++# ifdef __sgi
++# pragma pack 0
++# endif
++#endif
++
++void *ffi_closure_alloc (size_t size, void **code);
++void ffi_closure_free (void *);
+
+ffi_status
-+ffi_prep_raw_closure (ffi_raw_closure* cl,
-+ ffi_cif *cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data)
-+{
-+ return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
-+}
++ffi_prep_closure (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data);
+
-+#endif /* FFI_CLOSURES */
++ffi_status
++ffi_prep_closure_loc (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data,
++ void*codeloc);
+
-+#endif /* !FFI_NO_RAW_API */
-diff -Nru orig/Modules/_ctypes/libffi_ios/x86/darwin64_x86_64.S modified/Modules/_ctypes/libffi_ios/x86/darwin64_x86_64.S
---- orig/Modules/_ctypes/libffi_ios/x86/darwin64_x86_64.S 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/x86/darwin64_x86_64.S 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,421 @@
-+#ifdef __x86_64__
++#ifdef __sgi
++# pragma pack 8
++#endif
++typedef struct {
++#if 1
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++ ffi_cif *cif;
+
-+/* -----------------------------------------------------------------------
-+ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc.
-+ Copyright (c) 2008 Red Hat, Inc.
-+ derived from unix64.S
++#if !FFI_NATIVE_RAW_API
+
-+ x86-64 Foreign Function Interface for Darwin.
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++#endif
+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
-+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ OTHER DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void *user_data;
+
-+#ifdef __x86_64__
-+#define LIBFFI_ASM
-+#include
-+#include
++} ffi_raw_closure;
+
-+ .file "darwin64.S"
-+.text
++typedef struct {
++#if 1
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
+
-+/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
-+ void *raddr, void (*fnaddr)(void));
++ ffi_cif *cif;
+
-+ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
-+ for this function. This has been allocated by ffi_call. We also
-+ deallocate some of the stack that has been alloca'd. */
++#if !FFI_NATIVE_RAW_API
+
-+ .align 3
-+ .globl _ffi_call_unix64
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+_ffi_call_unix64:
-+LUW0:
-+ movq (%rsp), %r10 /* Load return address. */
-+ leaq (%rdi, %rsi), %rax /* Find local stack base. */
-+ movq %rdx, (%rax) /* Save flags. */
-+ movq %rcx, 8(%rax) /* Save raddr. */
-+ movq %rbp, 16(%rax) /* Save old frame pointer. */
-+ movq %r10, 24(%rax) /* Relocate return address. */
-+ movq %rax, %rbp /* Finalize local stack frame. */
-+LUW1:
-+ movq %rdi, %r10 /* Save a copy of the register area. */
-+ movq %r8, %r11 /* Save a copy of the target fn. */
-+ movl %r9d, %eax /* Set number of SSE registers. */
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+ /* Load up all argument registers. */
-+ movq (%r10), %rdi
-+ movq 8(%r10), %rsi
-+ movq 16(%r10), %rdx
-+ movq 24(%r10), %rcx
-+ movq 32(%r10), %r8
-+ movq 40(%r10), %r9
-+ testl %eax, %eax
-+ jnz Lload_sse
-+Lret_from_load_sse:
++#endif
+
-+ /* Deallocate the reg arg area. */
-+ leaq 176(%r10), %rsp
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
++ void *user_data;
+
-+ /* Call the user function. */
-+ call *%r11
++} ffi_java_raw_closure;
+
-+ /* Deallocate stack arg area; local stack frame in redzone. */
-+ leaq 24(%rbp), %rsp
++ffi_status
++ffi_prep_raw_closure (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data);
+
-+ movq 0(%rbp), %rcx /* Reload flags. */
-+ movq 8(%rbp), %rdi /* Reload raddr. */
-+ movq 16(%rbp), %rbp /* Reload old frame pointer. */
-+LUW2:
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+ /* The first byte of the flags contains the FFI_TYPE. */
-+ movzbl %cl, %r10d
-+ leaq Lstore_table(%rip), %r11
-+ movslq (%r11, %r10, 4), %r10
-+ addq %r11, %r10
-+ jmp *%r10
++ffi_status
++ffi_prep_java_raw_closure (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data);
++
++ffi_status
++ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+Lstore_table:
-+ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */
-+ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */
-+ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */
-+ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */
-+ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */
-+ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */
-+ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */
-+ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */
-+ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */
-+ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */
-+ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */
-+ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */
-+ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */
-+ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */
-+ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */
++#endif /* FFI_CLOSURES */
+
-+ .text
-+ .align 3
-+Lst_void:
-+ ret
-+ .align 3
-+Lst_uint8:
-+ movzbq %al, %rax
-+ movq %rax, (%rdi)
-+ ret
-+ .align 3
-+Lst_sint8:
-+ movsbq %al, %rax
-+ movq %rax, (%rdi)
-+ ret
-+ .align 3
-+Lst_uint16:
-+ movzwq %ax, %rax
-+ movq %rax, (%rdi)
-+ .align 3
-+Lst_sint16:
-+ movswq %ax, %rax
-+ movq %rax, (%rdi)
-+ ret
-+ .align 3
-+Lst_uint32:
-+ movl %eax, %eax
-+ movq %rax, (%rdi)
-+ .align 3
-+Lst_sint32:
-+ cltq
-+ movq %rax, (%rdi)
-+ ret
-+ .align 3
-+Lst_int64:
-+ movq %rax, (%rdi)
-+ ret
-+ .align 3
-+Lst_float:
-+ movss %xmm0, (%rdi)
-+ ret
-+ .align 3
-+Lst_double:
-+ movsd %xmm0, (%rdi)
-+ ret
-+Lst_ldouble:
-+ fstpt (%rdi)
-+ ret
-+ .align 3
-+Lst_struct:
-+ leaq -20(%rsp), %rsi /* Scratch area in redzone. */
-+
-+ /* We have to locate the values now, and since we don't want to
-+ write too much data into the user's return value, we spill the
-+ value to a 16 byte scratch area first. Bits 8, 9, and 10
-+ control where the values are located. Only one of the three
-+ bits will be set; see ffi_prep_cif_machdep for the pattern. */
-+ movd %xmm0, %r10
-+ movd %xmm1, %r11
-+ testl $0x100, %ecx
-+ cmovnz %rax, %rdx
-+ cmovnz %r10, %rax
-+ testl $0x200, %ecx
-+ cmovnz %r10, %rdx
-+ testl $0x400, %ecx
-+ cmovnz %r10, %rax
-+ cmovnz %r11, %rdx
-+ movq %rax, (%rsi)
-+ movq %rdx, 8(%rsi)
++#if FFI_GO_CLOSURES
+
-+ /* Bits 12-31 contain the true size of the structure. Copy from
-+ the scratch area to the true destination. */
-+ shrl $12, %ecx
-+ rep movsb
-+ ret
++typedef struct {
++ void *tramp;
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++} ffi_go_closure;
+
-+ /* Many times we can avoid loading any SSE registers at all.
-+ It's not worth an indirect jump to load the exact set of
-+ SSE registers needed; zero or all is a good compromise. */
-+ .align 3
-+LUW3:
-+Lload_sse:
-+ movdqa 48(%r10), %xmm0
-+ movdqa 64(%r10), %xmm1
-+ movdqa 80(%r10), %xmm2
-+ movdqa 96(%r10), %xmm3
-+ movdqa 112(%r10), %xmm4
-+ movdqa 128(%r10), %xmm5
-+ movdqa 144(%r10), %xmm6
-+ movdqa 160(%r10), %xmm7
-+ jmp Lret_from_load_sse
-+
-+LUW4:
-+ .align 3
-+ .globl _ffi_closure_unix64
-+
-+_ffi_closure_unix64:
-+LUW5:
-+ /* The carry flag is set by the trampoline iff SSE registers
-+ are used. Don't clobber it before the branch instruction. */
-+ leaq -200(%rsp), %rsp
-+LUW6:
-+ movq %rdi, (%rsp)
-+ movq %rsi, 8(%rsp)
-+ movq %rdx, 16(%rsp)
-+ movq %rcx, 24(%rsp)
-+ movq %r8, 32(%rsp)
-+ movq %r9, 40(%rsp)
-+ jc Lsave_sse
-+Lret_from_save_sse:
-+
-+ movq %r10, %rdi
-+ leaq 176(%rsp), %rsi
-+ movq %rsp, %rdx
-+ leaq 208(%rsp), %rcx
-+ call _ffi_closure_unix64_inner
++ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*));
+
-+ /* Deallocate stack frame early; return value is now in redzone. */
-+ addq $200, %rsp
-+LUW7:
++void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
++ void **avalue, void *closure);
+
-+ /* The first byte of the return value contains the FFI_TYPE. */
-+ movzbl %al, %r10d
-+ leaq Lload_table(%rip), %r11
-+ movslq (%r11, %r10, 4), %r10
-+ addq %r11, %r10
-+ jmp *%r10
++#endif /* FFI_GO_CLOSURES */
+
-+Lload_table:
-+ .long Lld_void-Lload_table /* FFI_TYPE_VOID */
-+ .long Lld_int32-Lload_table /* FFI_TYPE_INT */
-+ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */
-+ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */
-+ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */
-+ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */
-+ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */
-+ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */
-+ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */
-+ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */
-+ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */
-+ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */
-+ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */
-+ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */
-+ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */
++/* ---- Public interface definition -------------------------------------- */
+
-+ .text
-+ .align 3
-+Lld_void:
-+ ret
-+ .align 3
-+Lld_int8:
-+ movzbl -24(%rsp), %eax
-+ ret
-+ .align 3
-+Lld_int16:
-+ movzwl -24(%rsp), %eax
-+ ret
-+ .align 3
-+Lld_int32:
-+ movl -24(%rsp), %eax
-+ ret
-+ .align 3
-+Lld_int64:
-+ movq -24(%rsp), %rax
-+ ret
-+ .align 3
-+Lld_float:
-+ movss -24(%rsp), %xmm0
-+ ret
-+ .align 3
-+Lld_double:
-+ movsd -24(%rsp), %xmm0
-+ ret
-+ .align 3
-+Lld_ldouble:
-+ fldt -24(%rsp)
-+ ret
-+ .align 3
-+Lld_struct:
-+ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax,
-+ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading
-+ both rdx and xmm1 with the second word. For the remaining,
-+ bit 8 set means xmm0 gets the second word, and bit 9 means
-+ that rax gets the second word. */
-+ movq -24(%rsp), %rcx
-+ movq -16(%rsp), %rdx
-+ movq -16(%rsp), %xmm1
-+ testl $0x100, %eax
-+ cmovnz %rdx, %rcx
-+ movd %rcx, %xmm0
-+ testl $0x200, %eax
-+ movq -24(%rsp), %rax
-+ cmovnz %rdx, %rax
-+ ret
++ffi_status ffi_prep_cif(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ /* See the comment above Lload_sse; the same logic applies here. */
-+ .align 3
-+LUW8:
-+Lsave_sse:
-+ movdqa %xmm0, 48(%rsp)
-+ movdqa %xmm1, 64(%rsp)
-+ movdqa %xmm2, 80(%rsp)
-+ movdqa %xmm3, 96(%rsp)
-+ movdqa %xmm4, 112(%rsp)
-+ movdqa %xmm5, 128(%rsp)
-+ movdqa %xmm6, 144(%rsp)
-+ movdqa %xmm7, 160(%rsp)
-+ jmp Lret_from_save_sse
-+
-+LUW9:
-+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
-+EH_frame1:
-+ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */
-+ .long L$set$0
-+LSCIE1:
-+ .long 0x0 /* CIE Identifier Tag */
-+ .byte 0x1 /* CIE Version */
-+ .ascii "zR\0" /* CIE Augmentation */
-+ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */
-+ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */
-+ .byte 0x10 /* CIE RA Column */
-+ .byte 0x1 /* uleb128 0x1; Augmentation size */
-+ .byte 0x10 /* FDE Encoding (pcrel sdata4) */
-+ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
-+ .byte 0x7 /* uleb128 0x7 */
-+ .byte 0x8 /* uleb128 0x8 */
-+ .byte 0x90 /* DW_CFA_offset, column 0x10 */
-+ .byte 0x1
-+ .align 3
-+LECIE1:
-+ .globl _ffi_call_unix64.eh
-+_ffi_call_unix64.eh:
-+LSFDE1:
-+ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */
-+ .long L$set$1
-+LASFDE1:
-+ .long LASFDE1-EH_frame1 /* FDE CIE offset */
-+ .quad LUW0-. /* FDE initial location */
-+ .set L$set$2,LUW4-LUW0 /* FDE address range */
-+ .quad L$set$2
-+ .byte 0x0 /* Augmentation size */
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .set L$set$3,LUW1-LUW0
-+ .long L$set$3
++ffi_status ffi_prep_cif_var(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ /* New stack frame based off rbp. This is a itty bit of unwind
-+ trickery in that the CFA *has* changed. There is no easy way
-+ to describe it correctly on entry to the function. Fortunately,
-+ it doesn't matter too much since at all points we can correctly
-+ unwind back to ffi_call. Note that the location to which we
-+ moved the return address is (the new) CFA-8, so from the
-+ perspective of the unwind info, it hasn't moved. */
-+ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */
-+ .byte 0x6
-+ .byte 0x20
-+ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */
-+ .byte 0x2
-+ .byte 0xa /* DW_CFA_remember_state */
++void ffi_call(ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ void **avalue);
+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .set L$set$4,LUW2-LUW1
-+ .long L$set$4
-+ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
-+ .byte 0x7
-+ .byte 0x8
-+ .byte 0xc0+6 /* DW_CFA_restore, %rbp */
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .set L$set$5,LUW3-LUW2
-+ .long L$set$5
-+ .byte 0xb /* DW_CFA_restore_state */
++/* ---- Definitions shared with assembly code ---------------------------- */
+
-+ .align 3
-+LEFDE1:
-+ .globl _ffi_closure_unix64.eh
-+_ffi_closure_unix64.eh:
-+LSFDE3:
-+ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */
-+ .long L$set$6
-+LASFDE3:
-+ .long LASFDE3-EH_frame1 /* FDE CIE offset */
-+ .quad LUW5-. /* FDE initial location */
-+ .set L$set$7,LUW9-LUW5 /* FDE address range */
-+ .quad L$set$7
-+ .byte 0x0 /* Augmentation size */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .set L$set$8,LUW6-LUW5
-+ .long L$set$8
-+ .byte 0xe /* DW_CFA_def_cfa_offset */
-+ .byte 208,1 /* uleb128 208 */
-+ .byte 0xa /* DW_CFA_remember_state */
++#endif
+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .set L$set$9,LUW7-LUW6
-+ .long L$set$9
-+ .byte 0xe /* DW_CFA_def_cfa_offset */
-+ .byte 0x8
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++#if 0
++#define FFI_TYPE_LONGDOUBLE 4
++#else
++#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++#define FFI_TYPE_COMPLEX 15
+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .set L$set$10,LUW8-LUW7
-+ .long L$set$10
-+ .byte 0xb /* DW_CFA_restore_state */
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
+
-+ .align 3
-+LEFDE3:
-+ .subsections_via_symbols
++#ifdef __cplusplus
++}
++#endif
+
-+#endif /* __x86_64__ */
++#endif
+
+
+#endif
\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/x86/darwin_i386.S modified/Modules/_ctypes/libffi_ios/x86/darwin_i386.S
---- orig/Modules/_ctypes/libffi_ios/x86/darwin_i386.S 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/x86/darwin_i386.S 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,449 @@
-+#ifdef __i386__
-+
-+/* -----------------------------------------------------------------------
-+ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc.
-+ Copyright (C) 2008 Free Software Foundation, Inc.
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_armv7.h modified/Modules/_ctypes/libffi_ios/include/ffi_armv7.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi_armv7.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi_armv7.h 2015-12-20 18:55:29.000000000 +0800
+@@ -0,0 +1,508 @@
++#ifdef __arm__
+
-+ X86 Foreign Function Interface
++/* -----------------------------------------------------------------*-C-*-
++ libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green
++ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation
++ files (the ``Software''), to deal in the Software without
++ restriction, including without limitation the rights to use, copy,
++ modify, merge, publish, distribute, sublicense, and/or sell copies
++ of the Software, and to permit persons to whom the Software is
++ furnished to do so, subject to the following conditions:
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
@@ -30820,1140 +23544,705 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/x86/darwin_i386.S modified/Modules/_ct
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
-+ -----------------------------------------------------------------------
-+ */
-+
-+#ifndef __x86_64__
+
-+#define LIBFFI_ASM
-+#include
-+#include
++ ----------------------------------------------------------------------- */
+
-+.text
++/* -------------------------------------------------------------------
++ The basic API is described in the README file.
+
-+.globl _ffi_prep_args
++ The raw API is designed to bypass some of the argument packing
++ and unpacking on architectures for which it can be avoided.
+
-+ .align 4
-+.globl _ffi_call_SYSV
++ The closure API allows interpreted functions to be packaged up
++ inside a C function pointer, so that they can be called as C functions,
++ with no understanding on the client side that they are interpreted.
++ It can also be used in other cases in which it is necessary to package
++ up a user specified parameter and a function pointer as a single
++ function pointer.
+
-+_ffi_call_SYSV:
-+.LFB1:
-+ pushl %ebp
-+.LCFI0:
-+ movl %esp,%ebp
-+.LCFI1:
-+ subl $8,%esp
-+ /* Make room for all of the new args. */
-+ movl 16(%ebp),%ecx
-+ subl %ecx,%esp
++ The closure API must be implemented in order to get its functionality,
++ e.g. for use by gij. Routines are provided to emulate the raw API
++ if the underlying platform doesn't allow faster implementation.
+
-+ movl %esp,%eax
++ More details on the raw and cloure API can be found in:
+
-+ /* Place all of the ffi_prep_args in position */
-+ subl $8,%esp
-+ pushl 12(%ebp)
-+ pushl %eax
-+ call *8(%ebp)
++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
-+ /* Return stack to previous state and call the function */
-+ addl $16,%esp
++ and
+
-+ call *28(%ebp)
++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
++ -------------------------------------------------------------------- */
+
-+ /* Load %ecx with the return type code */
-+ movl 20(%ebp),%ecx
++#ifndef LIBFFI_H
++#define LIBFFI_H
+
-+ /* Protect %esi. We're going to pop it in the epilogue. */
-+ pushl %esi
++#ifdef __cplusplus
++extern "C" {
++#endif
+
-+ /* If the return value pointer is NULL, assume no return value. */
-+ cmpl $0,24(%ebp)
-+ jne 0f
++/* Specify which architecture libffi is configured for. */
++#ifndef ARM
++#define ARM
++#endif
+
-+ /* Even if there is no space for the return value, we are
-+ obliged to handle floating-point values. */
-+ cmpl $FFI_TYPE_FLOAT,%ecx
-+ jne noretval
-+ fstp %st(0)
++/* ---- System configuration information --------------------------------- */
+
-+ jmp epilogue
-+0:
-+ .align 4
-+ call 1f
-+.Lstore_table:
-+ .long noretval-.Lstore_table /* FFI_TYPE_VOID */
-+ .long retint-.Lstore_table /* FFI_TYPE_INT */
-+ .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */
-+ .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */
-+ .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */
-+ .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */
-+ .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */
-+ .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */
-+ .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */
-+ .long retint-.Lstore_table /* FFI_TYPE_UINT32 */
-+ .long retint-.Lstore_table /* FFI_TYPE_SINT32 */
-+ .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */
-+ .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */
-+ .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */
-+ .long retint-.Lstore_table /* FFI_TYPE_POINTER */
-+ .long retstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */
-+ .long retstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */
-+1:
-+ pop %esi
-+ add (%esi, %ecx, 4), %esi
-+ jmp *%esi
++#include
+
-+ /* Sign/zero extend as appropriate. */
-+retsint8:
-+ movsbl %al, %eax
-+ jmp retint
++#ifndef LIBFFI_ASM
+
-+retsint16:
-+ movswl %ax, %eax
-+ jmp retint
++#if defined(_MSC_VER) && !defined(__clang__)
++#define __attribute__(X)
++#endif
+
-+retuint8:
-+ movzbl %al, %eax
-+ jmp retint
++#include
++#include
+
-+retuint16:
-+ movzwl %ax, %eax
-+ jmp retint
-+
-+retfloat:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ fstps (%ecx)
-+ jmp epilogue
-+
-+retdouble:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ fstpl (%ecx)
-+ jmp epilogue
-+
-+retlongdouble:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ fstpt (%ecx)
-+ jmp epilogue
-+
-+retint64:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ movl %eax,0(%ecx)
-+ movl %edx,4(%ecx)
-+ jmp epilogue
-+
-+retstruct1b:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ movb %al,0(%ecx)
-+ jmp epilogue
-+
-+retstruct2b:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ movw %ax,0(%ecx)
-+ jmp epilogue
-+
-+retint:
-+ /* Load %ecx with the pointer to storage for the return value */
-+ movl 24(%ebp),%ecx
-+ movl %eax,0(%ecx)
-+
-+retstruct:
-+ /* Nothing to do! */
-+
-+noretval:
-+epilogue:
-+ popl %esi
-+ movl %ebp,%esp
-+ popl %ebp
-+ ret
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
+
-+.LFE1:
-+.ffi_call_SYSV_end:
++#define FFI_64_BIT_MAX 9223372036854775807
+
-+ .align 4
-+FFI_HIDDEN (ffi_closure_SYSV)
-+.globl _ffi_closure_SYSV
-+
-+_ffi_closure_SYSV:
-+.LFB2:
-+ pushl %ebp
-+.LCFI2:
-+ movl %esp, %ebp
-+.LCFI3:
-+ subl $40, %esp
-+ leal -24(%ebp), %edx
-+ movl %edx, -12(%ebp) /* resp */
-+ leal 8(%ebp), %edx
-+ movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
-+ leal -12(%ebp), %edx
-+ movl %edx, (%esp) /* &resp */
-+ movl %ebx, 8(%esp)
-+.LCFI7:
-+ call L_ffi_closure_SYSV_inner$stub
-+ movl 8(%esp), %ebx
-+ movl -12(%ebp), %ecx
-+ cmpl $FFI_TYPE_INT, %eax
-+ je .Lcls_retint
-+
-+ /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-+ FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */
-+ cmpl $FFI_TYPE_UINT64, %eax
-+ jge 0f
-+ cmpl $FFI_TYPE_UINT8, %eax
-+ jge .Lcls_retint
-+
-+0: cmpl $FFI_TYPE_FLOAT, %eax
-+ je .Lcls_retfloat
-+ cmpl $FFI_TYPE_DOUBLE, %eax
-+ je .Lcls_retdouble
-+ cmpl $FFI_TYPE_LONGDOUBLE, %eax
-+ je .Lcls_retldouble
-+ cmpl $FFI_TYPE_SINT64, %eax
-+ je .Lcls_retllong
-+ cmpl $FFI_TYPE_SMALL_STRUCT_1B, %eax
-+ je .Lcls_retstruct1b
-+ cmpl $FFI_TYPE_SMALL_STRUCT_2B, %eax
-+ je .Lcls_retstruct2b
-+ cmpl $FFI_TYPE_STRUCT, %eax
-+ je .Lcls_retstruct
-+.Lcls_epilogue:
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret
-+.Lcls_retint:
-+ movl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+.Lcls_retfloat:
-+ flds (%ecx)
-+ jmp .Lcls_epilogue
-+.Lcls_retdouble:
-+ fldl (%ecx)
-+ jmp .Lcls_epilogue
-+.Lcls_retldouble:
-+ fldt (%ecx)
-+ jmp .Lcls_epilogue
-+.Lcls_retllong:
-+ movl (%ecx), %eax
-+ movl 4(%ecx), %edx
-+ jmp .Lcls_epilogue
-+.Lcls_retstruct1b:
-+ movsbl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+.Lcls_retstruct2b:
-+ movswl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+.Lcls_retstruct:
-+ lea -8(%ebp),%esp
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret $4
-+.LFE2:
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif /* _AIX52 or newer */
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
++# ifndef __PPC64__
++# if defined (__IBMC__) || defined (__IBMCPP__)
++# define FFI_LONG_LONG_MAX LONGLONG_MAX
++# endif
++# endif /* __PPC64__ */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif
++# endif
++#endif
+
-+#if !FFI_NO_RAW_API
++/* The closure code assumes that this works on pointers, i.e. a size_t */
++/* can hold a pointer. */
+
-+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-+#define CIF_FLAGS_OFFSET 20
++typedef struct _ffi_type
++{
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++ struct _ffi_type **elements;
++} ffi_type;
+
-+ .align 4
-+FFI_HIDDEN (ffi_closure_raw_SYSV)
-+.globl _ffi_closure_raw_SYSV
-+
-+_ffi_closure_raw_SYSV:
-+.LFB3:
-+ pushl %ebp
-+.LCFI4:
-+ movl %esp, %ebp
-+.LCFI5:
-+ pushl %esi
-+.LCFI6:
-+ subl $36, %esp
-+ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
-+ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-+ movl %edx, 12(%esp) /* user_data */
-+ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
-+ movl %edx, 8(%esp) /* raw_args */
-+ leal -24(%ebp), %edx
-+ movl %edx, 4(%esp) /* &res */
-+ movl %esi, (%esp) /* cif */
-+ call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
-+ movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
-+ cmpl $FFI_TYPE_INT, %eax
-+ je .Lrcls_retint
-+
-+ /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16,
-+ FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */
-+ cmpl $FFI_TYPE_UINT64, %eax
-+ jge 0f
-+ cmpl $FFI_TYPE_UINT8, %eax
-+ jge .Lrcls_retint
-+0:
-+ cmpl $FFI_TYPE_FLOAT, %eax
-+ je .Lrcls_retfloat
-+ cmpl $FFI_TYPE_DOUBLE, %eax
-+ je .Lrcls_retdouble
-+ cmpl $FFI_TYPE_LONGDOUBLE, %eax
-+ je .Lrcls_retldouble
-+ cmpl $FFI_TYPE_SINT64, %eax
-+ je .Lrcls_retllong
-+.Lrcls_epilogue:
-+ addl $36, %esp
-+ popl %esi
-+ popl %ebp
-+ ret
-+.Lrcls_retint:
-+ movl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+.Lrcls_retfloat:
-+ flds -24(%ebp)
-+ jmp .Lrcls_epilogue
-+.Lrcls_retdouble:
-+ fldl -24(%ebp)
-+ jmp .Lrcls_epilogue
-+.Lrcls_retldouble:
-+ fldt -24(%ebp)
-+ jmp .Lrcls_epilogue
-+.Lrcls_retllong:
-+ movl -24(%ebp), %eax
-+ movl -20(%ebp), %edx
-+ jmp .Lrcls_epilogue
-+.LFE3:
-+#endif
-+
-+.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
-+L_ffi_closure_SYSV_inner$stub:
-+ .indirect_symbol _ffi_closure_SYSV_inner
-+ hlt ; hlt ; hlt ; hlt ; hlt
++#ifndef LIBFFI_HIDE_BASIC_TYPES
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++ #error "char size not supported"
++#endif
+
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
++#else
++ #error "short size not supported"
++#endif
+
-+.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
-+EH_frame1:
-+ .set L$set$0,LECIE1-LSCIE1
-+ .long L$set$0
-+LSCIE1:
-+ .long 0x0
-+ .byte 0x1
-+ .ascii "zR\0"
-+ .byte 0x1
-+ .byte 0x7c
-+ .byte 0x8
-+ .byte 0x1
-+ .byte 0x10
-+ .byte 0xc
-+ .byte 0x5
-+ .byte 0x4
-+ .byte 0x88
-+ .byte 0x1
-+ .align 2
-+LECIE1:
-+.globl _ffi_call_SYSV.eh
-+_ffi_call_SYSV.eh:
-+LSFDE1:
-+ .set L$set$1,LEFDE1-LASFDE1
-+ .long L$set$1
-+LASFDE1:
-+ .long LASFDE1-EH_frame1
-+ .long .LFB1-.
-+ .set L$set$2,.LFE1-.LFB1
-+ .long L$set$2
-+ .byte 0x0
-+ .byte 0x4
-+ .set L$set$3,.LCFI0-.LFB1
-+ .long L$set$3
-+ .byte 0xe
-+ .byte 0x8
-+ .byte 0x84
-+ .byte 0x2
-+ .byte 0x4
-+ .set L$set$4,.LCFI1-.LCFI0
-+ .long L$set$4
-+ .byte 0xd
-+ .byte 0x4
-+ .align 2
-+LEFDE1:
-+.globl _ffi_closure_SYSV.eh
-+_ffi_closure_SYSV.eh:
-+LSFDE2:
-+ .set L$set$5,LEFDE2-LASFDE2
-+ .long L$set$5
-+LASFDE2:
-+ .long LASFDE2-EH_frame1
-+ .long .LFB2-.
-+ .set L$set$6,.LFE2-.LFB2
-+ .long L$set$6
-+ .byte 0x0
-+ .byte 0x4
-+ .set L$set$7,.LCFI2-.LFB2
-+ .long L$set$7
-+ .byte 0xe
-+ .byte 0x8
-+ .byte 0x84
-+ .byte 0x2
-+ .byte 0x4
-+ .set L$set$8,.LCFI3-.LCFI2
-+ .long L$set$8
-+ .byte 0xd
-+ .byte 0x4
-+ .align 2
-+LEFDE2:
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
++#else
++ #error "int size not supported"
++#endif
+
-+#if !FFI_NO_RAW_API
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
++ #error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != FFI_64_BIT_MAX
++ #error "long size not supported"
++#endif
+
-+.globl _ffi_closure_raw_SYSV.eh
-+_ffi_closure_raw_SYSV.eh:
-+LSFDE3:
-+ .set L$set$10,LEFDE3-LASFDE3
-+ .long L$set$10
-+LASFDE3:
-+ .long LASFDE3-EH_frame1
-+ .long .LFB3-.
-+ .set L$set$11,.LFE3-.LFB3
-+ .long L$set$11
-+ .byte 0x0
-+ .byte 0x4
-+ .set L$set$12,.LCFI4-.LFB3
-+ .long L$set$12
-+ .byte 0xe
-+ .byte 0x8
-+ .byte 0x84
-+ .byte 0x2
-+ .byte 0x4
-+ .set L$set$13,.LCFI5-.LCFI4
-+ .long L$set$13
-+ .byte 0xd
-+ .byte 0x4
-+ .byte 0x4
-+ .set L$set$14,.LCFI6-.LCFI5
-+ .long L$set$14
-+ .byte 0x85
-+ .byte 0x3
-+ .align 2
-+LEFDE3:
++#if LONG_MAX == 2147483647
++# define ffi_type_ulong ffi_type_uint32
++# define ffi_type_slong ffi_type_sint32
++#elif LONG_MAX == FFI_64_BIT_MAX
++# define ffi_type_ulong ffi_type_uint64
++# define ffi_type_slong ffi_type_sint64
++#else
++ #error "long size not supported"
++#endif
+
++/* Need minimal decorations for DLLs to works on Windows. */
++/* GCC has autoimport and autoexport. Rely on Libtool to */
++/* help MSVC export from a DLL, but always declare data */
++/* to be imported for MSVC clients. This costs an extra */
++/* indirection for MSVC clients using the static version */
++/* of the library, but don't worry about that. Besides, */
++/* as a workaround, they can define FFI_BUILDING if they */
++/* *know* they are going to link with the static library. */
++#if defined _MSC_VER && !defined FFI_BUILDING
++#define FFI_EXTERN extern __declspec(dllimport)
++#else
++#define FFI_EXTERN extern
+#endif
+
-+#endif /* ifndef __x86_64__ */
++/* These are defined in types.c */
++FFI_EXTERN ffi_type ffi_type_void;
++FFI_EXTERN ffi_type ffi_type_uint8;
++FFI_EXTERN ffi_type ffi_type_sint8;
++FFI_EXTERN ffi_type ffi_type_uint16;
++FFI_EXTERN ffi_type ffi_type_sint16;
++FFI_EXTERN ffi_type ffi_type_uint32;
++FFI_EXTERN ffi_type ffi_type_sint32;
++FFI_EXTERN ffi_type ffi_type_uint64;
++FFI_EXTERN ffi_type ffi_type_sint64;
++FFI_EXTERN ffi_type ffi_type_float;
++FFI_EXTERN ffi_type ffi_type_double;
++FFI_EXTERN ffi_type ffi_type_pointer;
+
++#if 0
++FFI_EXTERN ffi_type ffi_type_longdouble;
++#else
++#define ffi_type_longdouble ffi_type_double
++#endif
+
++#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
++FFI_EXTERN ffi_type ffi_type_complex_float;
++FFI_EXTERN ffi_type ffi_type_complex_double;
++#if 0
++FFI_EXTERN ffi_type ffi_type_complex_longdouble;
++#else
++#define ffi_type_complex_longdouble ffi_type_complex_double
+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/x86/ffi64_x86_64.c modified/Modules/_ctypes/libffi_ios/x86/ffi64_x86_64.c
---- orig/Modules/_ctypes/libffi_ios/x86/ffi64_x86_64.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/x86/ffi64_x86_64.c 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,681 @@
-+#ifdef __x86_64__
++#endif
++#endif /* LIBFFI_HIDE_BASIC_TYPES */
+
-+/* -----------------------------------------------------------------------
-+ ffi64.c - Copyright (c) 2013 The Written Word, Inc.
-+ Copyright (c) 2011 Anthony Green
-+ Copyright (c) 2008, 2010 Red Hat, Inc.
-+ Copyright (c) 2002, 2007 Bo Thorsen
++typedef enum {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
+
-+ x86-64 Foreign Function Interface
++typedef unsigned FFI_TYPE;
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++typedef struct {
++ ffi_abi abi;
++ unsigned nargs;
++ ffi_type **arg_types;
++ ffi_type *rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++#if 0
++/* Used to adjust size/alignment of ffi types. */
++void ffi_prep_types (ffi_abi abi);
++#endif
+
-+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-+ DEALINGS IN THE SOFTWARE.
-+ ----------------------------------------------------------------------- */
++/* Used internally, but overridden by some architectures */
++ffi_status ffi_prep_cif_core(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int isvariadic,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+#include
-+#include
++/* ---- Definitions for the raw API -------------------------------------- */
+
-+#include
-+#include
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == FFI_64_BIT_MAX
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
+
-+#ifdef __x86_64__
++#ifndef FFI_SIZEOF_JAVA_RAW
++# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
++#endif
+
-+#define MAX_GPR_REGS 6
-+#define MAX_SSE_REGS 8
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
+
-+#if defined(__INTEL_COMPILER)
-+#include "xmmintrin.h"
-+#define UINT128 __m128
-+#else
-+#if defined(__SUNPRO_C)
-+#include
-+#define UINT128 __m128i
++#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
++/* This is a special case for mips64/n32 ABI (and perhaps others) where
++ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
++typedef union {
++ signed int sint;
++ unsigned int uint;
++ float flt;
++ char data[FFI_SIZEOF_JAVA_RAW];
++ void* ptr;
++} ffi_java_raw;
+#else
-+#define UINT128 __int128_t
-+#endif
++typedef ffi_raw ffi_java_raw;
+#endif
+
-+union big_int_union
-+{
-+ UINT32 i32;
-+ UINT64 i64;
-+ UINT128 i128;
-+};
-+
-+struct register_args
-+{
-+ /* Registers for argument passing. */
-+ UINT64 gpr[MAX_GPR_REGS];
-+ union big_int_union sse[MAX_SSE_REGS];
-+};
-+
-+extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
-+ void *raddr, void (*fnaddr)(void), unsigned ssecount);
-+
-+/* All reference to register classes here is identical to the code in
-+ gcc/config/i386/i386.c. Do *not* change one without the other. */
-+
-+/* Register class used for passing given 64bit part of the argument.
-+ These represent classes as documented by the PS ABI, with the
-+ exception of SSESF, SSEDF classes, that are basically SSE class,
-+ just gcc will use SF or DFmode move instead of DImode to avoid
-+ reformatting penalties.
-+
-+ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
-+ whenever possible (upper half does contain padding). */
-+enum x86_64_reg_class
-+ {
-+ X86_64_NO_CLASS,
-+ X86_64_INTEGER_CLASS,
-+ X86_64_INTEGERSI_CLASS,
-+ X86_64_SSE_CLASS,
-+ X86_64_SSESF_CLASS,
-+ X86_64_SSEDF_CLASS,
-+ X86_64_SSEUP_CLASS,
-+ X86_64_X87_CLASS,
-+ X86_64_X87UP_CLASS,
-+ X86_64_COMPLEX_X87_CLASS,
-+ X86_64_MEMORY_CLASS
-+ };
-+
-+#define MAX_CLASSES 4
+
-+#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
++void ffi_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_raw *avalue);
+
-+/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
-+ of this code is to classify each 8bytes of incoming argument by the register
-+ class and assign registers accordingly. */
++void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
++void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
++size_t ffi_raw_size (ffi_cif *cif);
+
-+/* Return the union class of CLASS1 and CLASS2.
-+ See the x86-64 PS ABI for details. */
++/* This is analogous to the raw API, except it uses Java parameter */
++/* packing, even on 64-bit machines. I.e. on 64-bit machines */
++/* longs and doubles are followed by an empty 64-bit word. */
+
-+static enum x86_64_reg_class
-+merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
-+{
-+ /* Rule #1: If both classes are equal, this is the resulting class. */
-+ if (class1 == class2)
-+ return class1;
++void ffi_java_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_java_raw *avalue);
+
-+ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
-+ the other class. */
-+ if (class1 == X86_64_NO_CLASS)
-+ return class2;
-+ if (class2 == X86_64_NO_CLASS)
-+ return class1;
++void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
++void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
++size_t ffi_java_raw_size (ffi_cif *cif);
+
-+ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
-+ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
-+ return X86_64_MEMORY_CLASS;
++/* ---- Definitions for closures ----------------------------------------- */
+
-+ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
-+ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
-+ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
-+ return X86_64_INTEGERSI_CLASS;
-+ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
-+ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
-+ return X86_64_INTEGER_CLASS;
++#if FFI_CLOSURES
+
-+ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
-+ MEMORY is used. */
-+ if (class1 == X86_64_X87_CLASS
-+ || class1 == X86_64_X87UP_CLASS
-+ || class1 == X86_64_COMPLEX_X87_CLASS
-+ || class2 == X86_64_X87_CLASS
-+ || class2 == X86_64_X87UP_CLASS
-+ || class2 == X86_64_COMPLEX_X87_CLASS)
-+ return X86_64_MEMORY_CLASS;
++#ifdef _MSC_VER
++__declspec(align(8))
++#endif
++typedef struct {
++#if 1
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void *user_data;
++#ifdef __GNUC__
++} ffi_closure __attribute__((aligned (8)));
++#else
++} ffi_closure;
++# ifdef __sgi
++# pragma pack 0
++# endif
++#endif
+
-+ /* Rule #6: Otherwise class SSE is used. */
-+ return X86_64_SSE_CLASS;
-+}
++void *ffi_closure_alloc (size_t size, void **code);
++void ffi_closure_free (void *);
+
-+/* Classify the argument of type TYPE and mode MODE.
-+ CLASSES will be filled by the register class used to pass each word
-+ of the operand. The number of words is returned. In case the parameter
-+ should be passed in memory, 0 is returned. As a special case for zero
-+ sized containers, classes[0] will be NO_CLASS and 1 is returned.
++ffi_status
++ffi_prep_closure (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data);
+
-+ See the x86-64 PS ABI for details.
-+*/
-+static size_t
-+classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
-+ size_t byte_offset)
-+{
-+ switch (type->type)
-+ {
-+ case FFI_TYPE_UINT8:
-+ case FFI_TYPE_SINT8:
-+ case FFI_TYPE_UINT16:
-+ case FFI_TYPE_SINT16:
-+ case FFI_TYPE_UINT32:
-+ case FFI_TYPE_SINT32:
-+ case FFI_TYPE_UINT64:
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_POINTER:
-+ {
-+ size_t size = byte_offset + type->size;
++ffi_status
++ffi_prep_closure_loc (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data,
++ void*codeloc);
+
-+ if (size <= 4)
-+ {
-+ classes[0] = X86_64_INTEGERSI_CLASS;
-+ return 1;
-+ }
-+ else if (size <= 8)
-+ {
-+ classes[0] = X86_64_INTEGER_CLASS;
-+ return 1;
-+ }
-+ else if (size <= 12)
-+ {
-+ classes[0] = X86_64_INTEGER_CLASS;
-+ classes[1] = X86_64_INTEGERSI_CLASS;
-+ return 2;
-+ }
-+ else if (size <= 16)
-+ {
-+ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
-+ return 2;
-+ }
-+ else
-+ FFI_ASSERT (0);
-+ }
-+ case FFI_TYPE_FLOAT:
-+ if (!(byte_offset % 8))
-+ classes[0] = X86_64_SSESF_CLASS;
-+ else
-+ classes[0] = X86_64_SSE_CLASS;
-+ return 1;
-+ case FFI_TYPE_DOUBLE:
-+ classes[0] = X86_64_SSEDF_CLASS;
-+ return 1;
-+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
-+ case FFI_TYPE_LONGDOUBLE:
-+ classes[0] = X86_64_X87_CLASS;
-+ classes[1] = X86_64_X87UP_CLASS;
-+ return 2;
++#ifdef __sgi
++# pragma pack 8
+#endif
-+ case FFI_TYPE_STRUCT:
-+ {
-+ const size_t UNITS_PER_WORD = 8;
-+ size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-+ ffi_type **ptr;
-+ int i;
-+ enum x86_64_reg_class subclasses[MAX_CLASSES];
++typedef struct {
++#if 1
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++ ffi_cif *cif;
+
-+ /* If the struct is larger than 32 bytes, pass it on the stack. */
-+ if (type->size > 32)
-+ return 0;
++#if !FFI_NATIVE_RAW_API
+
-+ for (i = 0; i < words; i++)
-+ classes[i] = X86_64_NO_CLASS;
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+ /* Zero sized arrays or structures are NO_CLASS. We return 0 to
-+ signalize memory class, so handle it as special case. */
-+ if (!words)
-+ {
-+ classes[0] = X86_64_NO_CLASS;
-+ return 1;
-+ }
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+ /* Merge the fields of structure. */
-+ for (ptr = type->elements; *ptr != NULL; ptr++)
-+ {
-+ size_t num;
++#endif
+
-+ byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void *user_data;
+
-+ num = classify_argument (*ptr, subclasses, byte_offset % 8);
-+ if (num == 0)
-+ return 0;
-+ for (i = 0; i < num; i++)
-+ {
-+ size_t pos = byte_offset / 8;
-+ classes[i + pos] =
-+ merge_classes (subclasses[i], classes[i + pos]);
-+ }
++} ffi_raw_closure;
+
-+ byte_offset += (*ptr)->size;
-+ }
++typedef struct {
++#if 1
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
+
-+ if (words > 2)
-+ {
-+ /* When size > 16 bytes, if the first one isn't
-+ X86_64_SSE_CLASS or any other ones aren't
-+ X86_64_SSEUP_CLASS, everything should be passed in
-+ memory. */
-+ if (classes[0] != X86_64_SSE_CLASS)
-+ return 0;
++ ffi_cif *cif;
+
-+ for (i = 1; i < words; i++)
-+ if (classes[i] != X86_64_SSEUP_CLASS)
-+ return 0;
-+ }
++#if !FFI_NATIVE_RAW_API
+
-+ /* Final merger cleanup. */
-+ for (i = 0; i < words; i++)
-+ {
-+ /* If one class is MEMORY, everything should be passed in
-+ memory. */
-+ if (classes[i] == X86_64_MEMORY_CLASS)
-+ return 0;
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+ /* The X86_64_SSEUP_CLASS should be always preceded by
-+ X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
-+ if (classes[i] == X86_64_SSEUP_CLASS
-+ && classes[i - 1] != X86_64_SSE_CLASS
-+ && classes[i - 1] != X86_64_SSEUP_CLASS)
-+ {
-+ /* The first one should never be X86_64_SSEUP_CLASS. */
-+ FFI_ASSERT (i != 0);
-+ classes[i] = X86_64_SSE_CLASS;
-+ }
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+ /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
-+ everything should be passed in memory. */
-+ if (classes[i] == X86_64_X87UP_CLASS
-+ && (classes[i - 1] != X86_64_X87_CLASS))
-+ {
-+ /* The first one should never be X86_64_X87UP_CLASS. */
-+ FFI_ASSERT (i != 0);
-+ return 0;
-+ }
-+ }
-+ return words;
-+ }
++#endif
+
-+ default:
-+ FFI_ASSERT(0);
-+ }
-+ return 0; /* Never reached. */
-+}
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
++ void *user_data;
+
-+/* Examine the argument and return set number of register required in each
-+ class. Return zero iff parameter should be passed in memory, otherwise
-+ the number of registers. */
++} ffi_java_raw_closure;
+
-+static size_t
-+examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
-+ _Bool in_return, int *pngpr, int *pnsse)
-+{
-+ size_t n;
-+ int i, ngpr, nsse;
++ffi_status
++ffi_prep_raw_closure (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data);
+
-+ n = classify_argument (type, classes, 0);
-+ if (n == 0)
-+ return 0;
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+ ngpr = nsse = 0;
-+ for (i = 0; i < n; ++i)
-+ switch (classes[i])
-+ {
-+ case X86_64_INTEGER_CLASS:
-+ case X86_64_INTEGERSI_CLASS:
-+ ngpr++;
-+ break;
-+ case X86_64_SSE_CLASS:
-+ case X86_64_SSESF_CLASS:
-+ case X86_64_SSEDF_CLASS:
-+ nsse++;
-+ break;
-+ case X86_64_NO_CLASS:
-+ case X86_64_SSEUP_CLASS:
-+ break;
-+ case X86_64_X87_CLASS:
-+ case X86_64_X87UP_CLASS:
-+ case X86_64_COMPLEX_X87_CLASS:
-+ return in_return != 0;
-+ default:
-+ abort ();
-+ }
++ffi_status
++ffi_prep_java_raw_closure (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data);
++
++ffi_status
++ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+ *pngpr = ngpr;
-+ *pnsse = nsse;
++#endif /* FFI_CLOSURES */
+
-+ return n;
-+}
++#if FFI_GO_CLOSURES
+
-+/* Perform machine dependent cif processing. */
++typedef struct {
++ void *tramp;
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++} ffi_go_closure;
+
-+ffi_status
-+ffi_prep_cif_machdep (ffi_cif *cif)
-+{
-+ int gprcount, ssecount, i, avn, ngpr, nsse, flags;
-+ enum x86_64_reg_class classes[MAX_CLASSES];
-+ size_t bytes, n;
++ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*));
+
-+ gprcount = ssecount = 0;
++void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
++ void **avalue, void *closure);
+
-+ flags = cif->rtype->type;
-+ if (flags != FFI_TYPE_VOID)
-+ {
-+ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
-+ if (n == 0)
-+ {
-+ /* The return value is passed in memory. A pointer to that
-+ memory is the first argument. Allocate a register for it. */
-+ gprcount++;
-+ /* We don't have to do anything in asm for the return. */
-+ flags = FFI_TYPE_VOID;
-+ }
-+ else if (flags == FFI_TYPE_STRUCT)
-+ {
-+ /* Mark which registers the result appears in. */
-+ _Bool sse0 = SSE_CLASS_P (classes[0]);
-+ _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
-+ if (sse0 && !sse1)
-+ flags |= 1 << 8;
-+ else if (!sse0 && sse1)
-+ flags |= 1 << 9;
-+ else if (sse0 && sse1)
-+ flags |= 1 << 10;
-+ /* Mark the true size of the structure. */
-+ flags |= cif->rtype->size << 12;
-+ }
-+ }
++#endif /* FFI_GO_CLOSURES */
+
-+ /* Go over all arguments and determine the way they should be passed.
-+ If it's in a register and there is space for it, let that be so. If
-+ not, add it's size to the stack byte count. */
-+ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
-+ {
-+ if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
-+ || gprcount + ngpr > MAX_GPR_REGS
-+ || ssecount + nsse > MAX_SSE_REGS)
-+ {
-+ long align = cif->arg_types[i]->alignment;
++/* ---- Public interface definition -------------------------------------- */
+
-+ if (align < 8)
-+ align = 8;
++ffi_status ffi_prep_cif(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ bytes = ALIGN (bytes, align);
-+ bytes += cif->arg_types[i]->size;
-+ }
-+ else
-+ {
-+ gprcount += ngpr;
-+ ssecount += nsse;
-+ }
-+ }
-+ if (ssecount)
-+ flags |= 1 << 11;
-+ cif->flags = flags;
-+ cif->bytes = (unsigned)ALIGN (bytes, 8);
++ffi_status ffi_prep_cif_var(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ return FFI_OK;
-+}
++void ffi_call(ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ void **avalue);
+
-+void
-+ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
-+{
-+ enum x86_64_reg_class classes[MAX_CLASSES];
-+ char *stack, *argp;
-+ ffi_type **arg_types;
-+ int gprcount, ssecount, ngpr, nsse, i, avn;
-+ _Bool ret_in_memory;
-+ struct register_args *reg_args;
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
+
-+ /* Can't call 32-bit mode from 64-bit mode. */
-+ FFI_ASSERT (cif->abi == FFI_UNIX64);
++/* ---- Definitions shared with assembly code ---------------------------- */
+
-+ /* If the return value is a struct and we don't have a return value
-+ address then we need to make one. Note the setting of flags to
-+ VOID above in ffi_prep_cif_machdep. */
-+ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
-+ && (cif->flags & 0xff) == FFI_TYPE_VOID);
-+ if (rvalue == NULL && ret_in_memory)
-+ rvalue = alloca (cif->rtype->size);
++#endif
+
-+ /* Allocate the space for the arguments, plus 4 words of temp space. */
-+ stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
-+ reg_args = (struct register_args *) stack;
-+ argp = stack + sizeof (struct register_args);
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++#if 0
++#define FFI_TYPE_LONGDOUBLE 4
++#else
++#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++#define FFI_TYPE_COMPLEX 15
+
-+ gprcount = ssecount = 0;
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
+
-+ /* If the return value is passed in memory, add the pointer as the
-+ first integer argument. */
-+ if (ret_in_memory)
-+ reg_args->gpr[gprcount++] = (unsigned long) rvalue;
++#ifdef __cplusplus
++}
++#endif
+
-+ avn = cif->nargs;
-+ arg_types = cif->arg_types;
++#endif
+
-+ for (i = 0; i < avn; ++i)
-+ {
-+ size_t n, size = arg_types[i]->size;
+
-+ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
-+ if (n == 0
-+ || gprcount + ngpr > MAX_GPR_REGS
-+ || ssecount + nsse > MAX_SSE_REGS)
-+ {
-+ long align = arg_types[i]->alignment;
++#endif
+\ No newline at end of file
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_cfi.h modified/Modules/_ctypes/libffi_ios/include/ffi_cfi.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi_cfi.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi_cfi.h 2015-12-20 18:55:19.000000000 +0800
+@@ -0,0 +1,55 @@
++/* -----------------------------------------------------------------------
++ ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc.
+
-+ /* Stack arguments are *always* at least 8 byte aligned. */
-+ if (align < 8)
-+ align = 8;
++ Conditionally assemble cfi directives. Only necessary for building libffi.
++ ----------------------------------------------------------------------- */
+
-+ /* Pass this argument in memory. */
-+ argp = (void *) ALIGN (argp, align);
-+ memcpy (argp, avalue[i], size);
-+ argp += size;
-+ }
-+ else
-+ {
-+ /* The argument is passed entirely in registers. */
-+ char *a = (char *) avalue[i];
-+ int j;
++#ifndef FFI_CFI_H
++#define FFI_CFI_H
+
-+ for (j = 0; j < n; j++, a += 8, size -= 8)
-+ {
-+ switch (classes[j])
-+ {
-+ case X86_64_INTEGER_CLASS:
-+ case X86_64_INTEGERSI_CLASS:
-+ /* Sign-extend integer arguments passed in general
-+ purpose registers, to cope with the fact that
-+ LLVM incorrectly assumes that this will be done
-+ (the x86-64 PS ABI does not specify this). */
-+ switch (arg_types[i]->type)
-+ {
-+ case FFI_TYPE_SINT8:
-+ *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
-+ break;
-+ case FFI_TYPE_SINT16:
-+ *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
-+ break;
-+ case FFI_TYPE_SINT32:
-+ *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
-+ break;
-+ default:
-+ reg_args->gpr[gprcount] = 0;
-+ memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
-+ }
-+ gprcount++;
-+ break;
-+ case X86_64_SSE_CLASS:
-+ case X86_64_SSEDF_CLASS:
-+ reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
-+ break;
-+ case X86_64_SSESF_CLASS:
-+ reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
-+ break;
-+ default:
-+ abort();
-+ }
-+ }
-+ }
-+ }
++#ifdef HAVE_AS_CFI_PSEUDO_OP
+
-+ ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
-+ cif->flags, rvalue, fn, ssecount);
-+}
++# define cfi_startproc .cfi_startproc
++# define cfi_endproc .cfi_endproc
++# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
++# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
++# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
++# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
++# define cfi_offset(reg, off) .cfi_offset reg, off
++# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
++# define cfi_register(r1, r2) .cfi_register r1, r2
++# define cfi_return_column(reg) .cfi_return_column reg
++# define cfi_restore(reg) .cfi_restore reg
++# define cfi_same_value(reg) .cfi_same_value reg
++# define cfi_undefined(reg) .cfi_undefined reg
++# define cfi_remember_state .cfi_remember_state
++# define cfi_restore_state .cfi_restore_state
++# define cfi_window_save .cfi_window_save
++# define cfi_personality(enc, exp) .cfi_personality enc, exp
++# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
++# define cfi_escape(...) .cfi_escape __VA_ARGS__
++
++#else
++
++# define cfi_startproc
++# define cfi_endproc
++# define cfi_def_cfa(reg, off)
++# define cfi_def_cfa_register(reg)
++# define cfi_def_cfa_offset(off)
++# define cfi_adjust_cfa_offset(off)
++# define cfi_offset(reg, off)
++# define cfi_rel_offset(reg, off)
++# define cfi_register(r1, r2)
++# define cfi_return_column(reg)
++# define cfi_restore(reg)
++# define cfi_same_value(reg)
++# define cfi_undefined(reg)
++# define cfi_remember_state
++# define cfi_restore_state
++# define cfi_window_save
++# define cfi_personality(enc, exp)
++# define cfi_lsda(enc, exp)
++# define cfi_escape(...)
++
++#endif /* HAVE_AS_CFI_PSEUDO_OP */
++#endif /* FFI_CFI_H */
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_common.h modified/Modules/_ctypes/libffi_ios/include/ffi_common.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi_common.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi_common.h 2015-12-20 18:55:19.000000000 +0800
+@@ -0,0 +1,132 @@
++/* -----------------------------------------------------------------------
++ ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green
++ Copyright (C) 2007 Free Software Foundation, Inc
++ Copyright (c) 1996 Red Hat, Inc.
++
++ Common internal definitions and macros. Only necessary for building
++ libffi.
++ ----------------------------------------------------------------------- */
+
++#ifndef FFI_COMMON_H
++#define FFI_COMMON_H
+
-+extern void ffi_closure_unix64(void);
++#ifdef __cplusplus
++extern "C" {
++#endif
+
-+ffi_status
-+ffi_prep_closure_loc (ffi_closure* closure,
-+ ffi_cif* cif,
-+ void (*fun)(ffi_cif*, void*, void**, void*),
-+ void *user_data,
-+ void *codeloc)
-+{
-+ volatile unsigned short *tramp;
++#include
+
-+ /* Sanity check on the cif ABI. */
-+ {
-+ int abi = cif->abi;
-+ if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
-+ return FFI_BAD_ABI;
-+ }
++/* Do not move this. Some versions of AIX are very picky about where
++ this is positioned. */
++#ifdef __GNUC__
++# if HAVE_ALLOCA_H
++# include
++# else
++ /* mingw64 defines this already in malloc.h. */
++# ifndef alloca
++# define alloca __builtin_alloca
++# endif
++# endif
++# define MAYBE_UNUSED __attribute__((__unused__))
++#else
++# define MAYBE_UNUSED
++# if HAVE_ALLOCA_H
++# include
++# else
++# ifdef _AIX
++# pragma alloca
++# else
++# ifndef alloca /* predefined by HP cc +Olibcalls */
++# ifdef _MSC_VER
++# define alloca _alloca
++# else
++char *alloca ();
++# endif
++# endif
++# endif
++# endif
++#endif
+
-+ tramp = (volatile unsigned short *) &closure->tramp[0];
++/* Check for the existence of memcpy. */
++#if STDC_HEADERS
++# include
++#else
++# ifndef HAVE_MEMCPY
++# define memcpy(d, s, n) bcopy ((s), (d), (n))
++# endif
++#endif
+
-+ tramp[0] = 0xbb49; /* mov , %r11 */
-+ *((unsigned long long * volatile) &tramp[1])
-+ = (unsigned long) ffi_closure_unix64;
-+ tramp[5] = 0xba49; /* mov , %r10 */
-+ *((unsigned long long * volatile) &tramp[6])
-+ = (unsigned long) codeloc;
++#if defined(FFI_DEBUG)
++#include
++#endif
+
-+ /* Set the carry bit iff the function uses any sse registers.
-+ This is clc or stc, together with the first byte of the jmp. */
-+ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
++#ifdef FFI_DEBUG
++void ffi_assert(char *expr, char *file, int line);
++void ffi_stop_here(void);
++void ffi_type_test(ffi_type *a, char *file, int line);
+
-+ tramp[11] = 0xe3ff; /* jmp *%r11 */
++#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
++#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
++#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
++#else
++#define FFI_ASSERT(x)
++#define FFI_ASSERT_AT(x, f, l)
++#define FFI_ASSERT_VALID_TYPE(x)
++#endif
+
-+ closure->cif = cif;
-+ closure->fun = fun;
-+ closure->user_data = user_data;
++#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
++#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
+
-+ return FFI_OK;
-+}
++/* Perform machine dependent cif processing */
++ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
++ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
++ unsigned int nfixedargs, unsigned int ntotalargs);
+
-+int
-+ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
-+ struct register_args *reg_args, char *argp)
++/* Extended cif, used in callback from assembly routine */
++typedef struct
+{
+ ffi_cif *cif;
++ void *rvalue;
+ void **avalue;
-+ ffi_type **arg_types;
-+ long i, avn;
-+ int gprcount, ssecount, ngpr, nsse;
-+ int ret;
-+
-+ cif = closure->cif;
-+ avalue = alloca(cif->nargs * sizeof(void *));
-+ gprcount = ssecount = 0;
-+
-+ ret = cif->rtype->type;
-+ if (ret != FFI_TYPE_VOID)
-+ {
-+ enum x86_64_reg_class classes[MAX_CLASSES];
-+ size_t n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
-+ if (n == 0)
-+ {
-+ /* The return value goes in memory. Arrange for the closure
-+ return value to go directly back to the original caller. */
-+ rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
-+ /* We don't have to do anything in asm for the return. */
-+ ret = FFI_TYPE_VOID;
-+ }
-+ else if (ret == FFI_TYPE_STRUCT && n == 2)
-+ {
-+ /* Mark which register the second word of the structure goes in. */
-+ _Bool sse0 = SSE_CLASS_P (classes[0]);
-+ _Bool sse1 = SSE_CLASS_P (classes[1]);
-+ if (!sse0 && sse1)
-+ ret |= 1 << 8;
-+ else if (sse0 && !sse1)
-+ ret |= 1 << 9;
-+ }
-+ }
-+
-+ avn = cif->nargs;
-+ arg_types = cif->arg_types;
-+
-+ for (i = 0; i < avn; ++i)
-+ {
-+ enum x86_64_reg_class classes[MAX_CLASSES];
-+ size_t n;
-+
-+ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
-+ if (n == 0
-+ || gprcount + ngpr > MAX_GPR_REGS
-+ || ssecount + nsse > MAX_SSE_REGS)
-+ {
-+ long align = arg_types[i]->alignment;
-+
-+ /* Stack arguments are *always* at least 8 byte aligned. */
-+ if (align < 8)
-+ align = 8;
++} extended_cif;
+
-+ /* Pass this argument in memory. */
-+ argp = (void *) ALIGN (argp, align);
-+ avalue[i] = argp;
-+ argp += arg_types[i]->size;
-+ }
-+ /* If the argument is in a single register, or two consecutive
-+ integer registers, then we can use that address directly. */
-+ else if (n == 1
-+ || (n == 2 && !(SSE_CLASS_P (classes[0])
-+ || SSE_CLASS_P (classes[1]))))
-+ {
-+ /* The argument is in a single register. */
-+ if (SSE_CLASS_P (classes[0]))
-+ {
-+ avalue[i] = ®_args->sse[ssecount];
-+ ssecount += n;
-+ }
-+ else
-+ {
-+ avalue[i] = ®_args->gpr[gprcount];
-+ gprcount += n;
-+ }
-+ }
-+ /* Otherwise, allocate space to make them consecutive. */
-+ else
-+ {
-+ char *a = alloca (16);
-+ int j;
++/* Terse sized type definitions. */
++#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C)
++typedef unsigned char UINT8;
++typedef signed char SINT8;
++typedef unsigned short UINT16;
++typedef signed short SINT16;
++typedef unsigned int UINT32;
++typedef signed int SINT32;
++# ifdef _MSC_VER
++typedef unsigned __int64 UINT64;
++typedef signed __int64 SINT64;
++# else
++# include
++typedef uint64_t UINT64;
++typedef int64_t SINT64;
++# endif
++#else
++typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
++typedef signed int SINT8 __attribute__((__mode__(__QI__)));
++typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
++typedef signed int SINT16 __attribute__((__mode__(__HI__)));
++typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
++typedef signed int SINT32 __attribute__((__mode__(__SI__)));
++typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
++typedef signed int SINT64 __attribute__((__mode__(__DI__)));
++#endif
+
-+ avalue[i] = a;
-+ for (j = 0; j < n; j++, a += 8)
-+ {
-+ if (SSE_CLASS_P (classes[j]))
-+ memcpy (a, ®_args->sse[ssecount++], 8);
-+ else
-+ memcpy (a, ®_args->gpr[gprcount++], 8);
-+ }
-+ }
-+ }
++typedef float FLOAT32;
+
-+ /* Invoke the closure. */
-+ closure->fun (cif, rvalue, avalue, closure->user_data);
++#ifndef __GNUC__
++#define __builtin_expect(x, expected_value) (x)
++#endif
++#define LIKELY(x) __builtin_expect(!!(x),1)
++#define UNLIKELY(x) __builtin_expect((x)!=0,0)
+
-+ /* Tell assembly how to perform return type promotions. */
-+ return ret;
++#ifdef __cplusplus
+}
-+
-+#endif /* __x86_64__ */
-+
++#endif
+
+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/x86/ffi_i386.c modified/Modules/_ctypes/libffi_ios/x86/ffi_i386.c
---- orig/Modules/_ctypes/libffi_ios/x86/ffi_i386.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/x86/ffi_i386.c 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,936 @@
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_i386.h modified/Modules/_ctypes/libffi_ios/include/ffi_i386.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi_i386.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi_i386.h 2015-12-20 18:55:29.000000000 +0800
+@@ -0,0 +1,508 @@
+#ifdef __i386__
+
-+/* -----------------------------------------------------------------------
-+ ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
-+ Copyright (c) 2002 Ranjit Mathew
-+ Copyright (c) 2002 Bo Thorsen
-+ Copyright (c) 2002 Roger Sayle
-+ Copyright (C) 2008, 2010 Free Software Foundation, Inc.
-+
-+ x86 Foreign Function Interface
++/* -----------------------------------------------------------------*-C-*-
++ libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green
++ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation
++ files (the ``Software''), to deal in the Software without
++ restriction, including without limitation the rights to use, copy,
++ modify, merge, publish, distribute, sublicense, and/or sell copies
++ of the Software, and to permit persons to whom the Software is
++ furnished to do so, subject to the following conditions:
+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
@@ -31963,940 +24252,511 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/x86/ffi_i386.c modified/Modules/_ctype
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
++
+ ----------------------------------------------------------------------- */
+
-+#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
++/* -------------------------------------------------------------------
++ The basic API is described in the README file.
+
-+#ifdef _WIN64
-+#include
-+#endif
++ The raw API is designed to bypass some of the argument packing
++ and unpacking on architectures for which it can be avoided.
+
-+#include
-+#include
++ The closure API allows interpreted functions to be packaged up
++ inside a C function pointer, so that they can be called as C functions,
++ with no understanding on the client side that they are interpreted.
++ It can also be used in other cases in which it is necessary to package
++ up a user specified parameter and a function pointer as a single
++ function pointer.
+
-+#include
++ The closure API must be implemented in order to get its functionality,
++ e.g. for use by gij. Routines are provided to emulate the raw API
++ if the underlying platform doesn't allow faster implementation.
++
++ More details on the raw and cloure API can be found in:
+
++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
-+/* ffi_prep_args is called by the assembly routine once stack space
-+ has been allocated for the function's arguments */
++ and
+
-+unsigned int ffi_prep_args(char *stack, extended_cif *ecif);
-+unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
-+{
-+ register unsigned int i;
-+ register void **p_argv;
-+ register char *argp;
-+ register ffi_type **p_arg;
-+#ifndef X86_WIN64
-+ const int cabi = ecif->cif->abi;
-+ const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1;
-+ unsigned int stack_args_count = 0;
-+ void *p_stack_data[3];
-+ char *argp2 = stack;
-+#else
-+ #define dir 1
-+#endif
++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
++ -------------------------------------------------------------------- */
+
-+ argp = stack;
++#ifndef LIBFFI_H
++#define LIBFFI_H
+
-+ if ((ecif->cif->flags == FFI_TYPE_STRUCT
-+ || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
-+#ifdef X86_WIN64
-+ && ((ecif->cif->rtype->size & (1 | 2 | 4 | 8)) == 0)
-+#endif
-+ )
-+ {
-+#ifndef X86_WIN64
-+ /* For fastcall/thiscall/register this is first register-passed
-+ argument. */
-+ if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL || cabi == FFI_REGISTER)
-+ {
-+ p_stack_data[stack_args_count] = argp;
-+ ++stack_args_count;
-+ }
++#ifdef __cplusplus
++extern "C" {
+#endif
+
-+ *(void **) argp = ecif->rvalue;
-+ argp += sizeof(void*);
-+ }
++/* Specify which architecture libffi is configured for. */
++#ifndef X86_DARWIN
++#define X86_DARWIN
++#endif
+
-+ p_arg = ecif->cif->arg_types;
-+ p_argv = ecif->avalue;
-+ if (dir < 0)
-+ {
-+ const int nargs = ecif->cif->nargs - 1;
-+ if (nargs > 0)
-+ {
-+ p_arg += nargs;
-+ p_argv += nargs;
-+ }
-+ }
++/* ---- System configuration information --------------------------------- */
+
-+ for (i = ecif->cif->nargs;
-+ i != 0;
-+ i--, p_arg += dir, p_argv += dir)
-+ {
-+ /* Align if necessary */
-+ if ((sizeof(void*) - 1) & (size_t) argp)
-+ argp = (char *) ALIGN(argp, sizeof(void*));
++#include
+
-+ size_t z = (*p_arg)->size;
++#ifndef LIBFFI_ASM
+
-+#ifdef X86_WIN64
-+ if (z > FFI_SIZEOF_ARG
-+ || ((*p_arg)->type == FFI_TYPE_STRUCT
-+ && (z & (1 | 2 | 4 | 8)) == 0)
-+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
-+ || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
-+#endif
-+ )
-+ {
-+ z = FFI_SIZEOF_ARG;
-+ *(void **)argp = *p_argv;
-+ }
-+ else if ((*p_arg)->type == FFI_TYPE_FLOAT)
-+ {
-+ memcpy(argp, *p_argv, z);
-+ }
-+ else
++#if defined(_MSC_VER) && !defined(__clang__)
++#define __attribute__(X)
+#endif
-+ if (z < FFI_SIZEOF_ARG)
-+ {
-+ z = FFI_SIZEOF_ARG;
-+ switch ((*p_arg)->type)
-+ {
-+ case FFI_TYPE_SINT8:
-+ *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_UINT8:
-+ *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_SINT16:
-+ *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_UINT16:
-+ *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_SINT32:
-+ *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_UINT32:
-+ *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
-+ break;
-+
-+ case FFI_TYPE_STRUCT:
-+ *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
-+ break;
-+
-+ default:
-+ FFI_ASSERT(0);
-+ }
-+ }
-+ else
-+ {
-+ memcpy(argp, *p_argv, z);
-+ }
+
-+#ifndef X86_WIN64
-+ /* For thiscall/fastcall/register convention register-passed arguments
-+ are the first two none-floating-point arguments with a size
-+ smaller or equal to sizeof (void*). */
-+ if ((z == FFI_SIZEOF_ARG)
-+ && ((cabi == FFI_REGISTER)
-+ || (cabi == FFI_THISCALL && stack_args_count < 1)
-+ || (cabi == FFI_FASTCALL && stack_args_count < 2))
-+ && ((*p_arg)->type != FFI_TYPE_FLOAT && (*p_arg)->type != FFI_TYPE_STRUCT)
-+ )
-+ {
-+ if (dir < 0 && stack_args_count > 2)
-+ {
-+ /* Iterating arguments backwards, so first register-passed argument
-+ will be passed last. Shift temporary values to make place. */
-+ p_stack_data[0] = p_stack_data[1];
-+ p_stack_data[1] = p_stack_data[2];
-+ stack_args_count = 2;
-+ }
++#include
++#include
+
-+ p_stack_data[stack_args_count] = argp;
-+ ++stack_args_count;
-+ }
-+#endif
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
+
-+#ifdef X86_WIN64
-+ argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
++#define FFI_64_BIT_MAX 9223372036854775807
++
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
+#else
-+ argp += z;
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif /* _AIX52 or newer */
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
++# ifndef __PPC64__
++# if defined (__IBMC__) || defined (__IBMCPP__)
++# define FFI_LONG_LONG_MAX LONGLONG_MAX
++# endif
++# endif /* __PPC64__ */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif
++# endif
+#endif
-+ }
-+
-+#ifndef X86_WIN64
-+ /* We need to move the register-passed arguments for thiscall/fastcall/register
-+ on top of stack, so that those can be moved to registers by call-handler. */
-+ if (stack_args_count > 0)
-+ {
-+ if (dir < 0 && stack_args_count > 1)
-+ {
-+ /* Reverse order if iterating arguments backwards */
-+ ffi_arg tmp = *(ffi_arg*) p_stack_data[0];
-+ *(ffi_arg*) p_stack_data[0] = *(ffi_arg*) p_stack_data[stack_args_count - 1];
-+ *(ffi_arg*) p_stack_data[stack_args_count - 1] = tmp;
-+ }
-+
-+ int i;
-+ for (i = 0; i < stack_args_count; i++)
-+ {
-+ if (p_stack_data[i] != argp2)
-+ {
-+ ffi_arg tmp = *(ffi_arg*) p_stack_data[i];
-+ memmove (argp2 + FFI_SIZEOF_ARG, argp2, (size_t) ((char*) p_stack_data[i] - (char*)argp2));
-+ *(ffi_arg *) argp2 = tmp;
-+ }
+
-+ argp2 += FFI_SIZEOF_ARG;
-+ }
-+ }
-+
-+ return stack_args_count;
-+#endif
-+ return 0;
-+}
++/* The closure code assumes that this works on pointers, i.e. a size_t */
++/* can hold a pointer. */
+
-+/* Perform machine dependent cif processing */
-+ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
++typedef struct _ffi_type
+{
-+ unsigned int i;
-+ ffi_type **ptr;
-+
-+ /* Set the return type flag */
-+ switch (cif->rtype->type)
-+ {
-+ case FFI_TYPE_VOID:
-+ case FFI_TYPE_UINT8:
-+ case FFI_TYPE_UINT16:
-+ case FFI_TYPE_SINT8:
-+ case FFI_TYPE_SINT16:
-+#ifdef X86_WIN64
-+ case FFI_TYPE_UINT32:
-+ case FFI_TYPE_SINT32:
-+#endif
-+ case FFI_TYPE_SINT64:
-+ case FFI_TYPE_FLOAT:
-+ case FFI_TYPE_DOUBLE:
-+#ifndef X86_WIN64
-+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
-+ case FFI_TYPE_LONGDOUBLE:
-+#endif
-+#endif
-+ cif->flags = (unsigned) cif->rtype->type;
-+ break;
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++ struct _ffi_type **elements;
++} ffi_type;
+
-+ case FFI_TYPE_UINT64:
-+#ifdef X86_WIN64
-+ case FFI_TYPE_POINTER:
++#ifndef LIBFFI_HIDE_BASIC_TYPES
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
++#else
++ #error "char size not supported"
+#endif
-+ cif->flags = FFI_TYPE_SINT64;
-+ break;
+
-+ case FFI_TYPE_STRUCT:
-+#ifndef X86
-+ if (cif->rtype->size == 1)
-+ {
-+ cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
-+ }
-+ else if (cif->rtype->size == 2)
-+ {
-+ cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
-+ }
-+ else if (cif->rtype->size == 4)
-+ {
-+#ifdef X86_WIN64
-+ cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
+#else
-+ cif->flags = FFI_TYPE_INT; /* same as int type */
-+#endif
-+ }
-+ else if (cif->rtype->size == 8)
-+ {
-+ cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
-+ }
-+ else
-+#endif
-+ {
-+#ifdef X86_WIN32
-+ if (cif->abi == FFI_MS_CDECL)
-+ cif->flags = FFI_TYPE_MS_STRUCT;
-+ else
++ #error "short size not supported"
+#endif
-+ cif->flags = FFI_TYPE_STRUCT;
-+ /* allocate space for return value pointer */
-+ cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
-+ }
-+ break;
+
-+ default:
-+#ifdef X86_WIN64
-+ cif->flags = FFI_TYPE_SINT64;
-+ break;
-+ case FFI_TYPE_INT:
-+ cif->flags = FFI_TYPE_SINT32;
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
+#else
-+ cif->flags = FFI_TYPE_INT;
++ #error "int size not supported"
+#endif
-+ break;
-+ }
-+
-+ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
-+ {
-+ if (((*ptr)->alignment - 1) & cif->bytes)
-+ cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
-+ cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
-+ }
+
-+#ifdef X86_WIN64
-+ /* ensure space for storing four registers */
-+ cif->bytes += 4 * FFI_SIZEOF_ARG;
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
++ #error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != FFI_64_BIT_MAX
++ #error "long size not supported"
+#endif
+
-+#ifndef X86_WIN32
-+#ifndef X86_WIN64
-+ if (cif->abi == FFI_SYSV || cif->abi == FFI_UNIX64)
-+#endif
-+ cif->bytes = (cif->bytes + 15) & ~0xF;
++#if LONG_MAX == 2147483647
++# define ffi_type_ulong ffi_type_uint32
++# define ffi_type_slong ffi_type_sint32
++#elif LONG_MAX == FFI_64_BIT_MAX
++# define ffi_type_ulong ffi_type_uint64
++# define ffi_type_slong ffi_type_sint64
++#else
++ #error "long size not supported"
+#endif
+
-+ return FFI_OK;
-+}
-+
-+#ifdef X86_WIN64
-+extern int
-+ffi_call_win64(unsigned int (*)(char *, extended_cif *), extended_cif *,
-+ unsigned, unsigned, unsigned *, void (*fn)(void));
++/* Need minimal decorations for DLLs to works on Windows. */
++/* GCC has autoimport and autoexport. Rely on Libtool to */
++/* help MSVC export from a DLL, but always declare data */
++/* to be imported for MSVC clients. This costs an extra */
++/* indirection for MSVC clients using the static version */
++/* of the library, but don't worry about that. Besides, */
++/* as a workaround, they can define FFI_BUILDING if they */
++/* *know* they are going to link with the static library. */
++#if defined _MSC_VER && !defined FFI_BUILDING
++#define FFI_EXTERN extern __declspec(dllimport)
+#else
-+extern void
-+ffi_call_win32(unsigned int (*)(char *, extended_cif *), extended_cif *,
-+ unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
-+extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
-+ unsigned, unsigned, unsigned *, void (*fn)(void));
++#define FFI_EXTERN extern
+#endif
+
-+void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
-+{
-+ extended_cif ecif;
-+
-+ ecif.cif = cif;
-+ ecif.avalue = avalue;
-+
-+ /* If the return value is a struct and we don't have a return */
-+ /* value address then we need to make one */
++/* These are defined in types.c */
++FFI_EXTERN ffi_type ffi_type_void;
++FFI_EXTERN ffi_type ffi_type_uint8;
++FFI_EXTERN ffi_type ffi_type_sint8;
++FFI_EXTERN ffi_type ffi_type_uint16;
++FFI_EXTERN ffi_type ffi_type_sint16;
++FFI_EXTERN ffi_type ffi_type_uint32;
++FFI_EXTERN ffi_type ffi_type_sint32;
++FFI_EXTERN ffi_type ffi_type_uint64;
++FFI_EXTERN ffi_type ffi_type_sint64;
++FFI_EXTERN ffi_type ffi_type_float;
++FFI_EXTERN ffi_type ffi_type_double;
++FFI_EXTERN ffi_type ffi_type_pointer;
+
-+#ifdef X86_WIN64
-+ if (rvalue == NULL
-+ && cif->flags == FFI_TYPE_STRUCT
-+ && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0))
-+ {
-+ ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
-+ }
++#if 1
++FFI_EXTERN ffi_type ffi_type_longdouble;
+#else
-+ if (rvalue == NULL
-+ && (cif->flags == FFI_TYPE_STRUCT
-+ || cif->flags == FFI_TYPE_MS_STRUCT))
-+ {
-+ ecif.rvalue = alloca(cif->rtype->size);
-+ }
++#define ffi_type_longdouble ffi_type_double
+#endif
-+ else
-+ ecif.rvalue = rvalue;
-+
-+
-+ switch (cif->abi)
-+ {
-+#ifdef X86_WIN64
-+ case FFI_WIN64:
-+ ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
-+ cif->flags, ecif.rvalue, fn);
-+ break;
-+#else
-+#ifndef X86_WIN32
-+ case FFI_SYSV:
-+ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
-+ fn);
-+ break;
++
++#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
++FFI_EXTERN ffi_type ffi_type_complex_float;
++FFI_EXTERN ffi_type ffi_type_complex_double;
++#if 1
++FFI_EXTERN ffi_type ffi_type_complex_longdouble;
+#else
-+ case FFI_SYSV:
-+ case FFI_MS_CDECL:
++#define ffi_type_complex_longdouble ffi_type_complex_double
+#endif
-+ case FFI_STDCALL:
-+ case FFI_THISCALL:
-+ case FFI_FASTCALL:
-+ case FFI_PASCAL:
-+ case FFI_REGISTER:
-+ ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
-+ ecif.rvalue, fn);
-+ break;
+#endif
-+ default:
-+ FFI_ASSERT(0);
-+ break;
-+ }
-+}
++#endif /* LIBFFI_HIDE_BASIC_TYPES */
+
++typedef enum {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
+
-+/** private members **/
++typedef unsigned FFI_TYPE;
+
-+/* The following __attribute__((regparm(1))) decorations will have no effect
-+ on MSVC or SUNPRO_C -- standard conventions apply. */
-+static unsigned int ffi_prep_incoming_args (char *stack, void **ret,
-+ void** args, ffi_cif* cif);
-+void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
-+ __attribute__ ((regparm(1)));
-+unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
-+ __attribute__ ((regparm(1)));
-+unsigned int FFI_HIDDEN ffi_closure_WIN32_inner (ffi_closure *, void **, void *)
-+ __attribute__ ((regparm(1)));
-+void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
-+ __attribute__ ((regparm(1)));
-+#ifdef X86_WIN32
-+void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
-+ __attribute__ ((regparm(1)));
-+#endif
-+#ifndef X86_WIN64
-+void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *);
-+void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *);
-+void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *);
-+void FFI_HIDDEN ffi_closure_REGISTER (ffi_closure *);
-+#else
-+void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
++typedef struct {
++ ffi_abi abi;
++ unsigned nargs;
++ ffi_type **arg_types;
++ ffi_type *rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
+#endif
++} ffi_cif;
+
-+/* This function is jumped to by the trampoline */
++#if 0
++/* Used to adjust size/alignment of ffi types. */
++void ffi_prep_types (ffi_abi abi);
++#endif
+
-+#ifdef X86_WIN64
-+void * FFI_HIDDEN
-+ffi_closure_win64_inner (ffi_closure *closure, void *args) {
-+ ffi_cif *cif;
-+ void **arg_area;
-+ void *result;
-+ void *resp = &result;
-+
-+ cif = closure->cif;
-+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
-+
-+ /* this call will initialize ARG_AREA, such that each
-+ * element in that array points to the corresponding
-+ * value on the stack; and if the function returns
-+ * a structure, it will change RESP to point to the
-+ * structure return address. */
-+
-+ ffi_prep_incoming_args(args, &resp, arg_area, cif);
-+
-+ (closure->fun) (cif, resp, arg_area, closure->user_data);
++/* Used internally, but overridden by some architectures */
++ffi_status ffi_prep_cif_core(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int isvariadic,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ /* The result is returned in rax. This does the right thing for
-+ result types except for floats; we have to 'mov xmm0, rax' in the
-+ caller to correct this.
-+ TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
-+ */
-+ return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
-+}
++/* ---- Definitions for the raw API -------------------------------------- */
+
-+#else
-+unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
-+ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
-+{
-+ /* our various things... */
-+ ffi_cif *cif;
-+ void **arg_area;
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == FFI_64_BIT_MAX
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
+
-+ cif = closure->cif;
-+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
++#ifndef FFI_SIZEOF_JAVA_RAW
++# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
++#endif
+
-+ /* this call will initialize ARG_AREA, such that each
-+ * element in that array points to the corresponding
-+ * value on the stack; and if the function returns
-+ * a structure, it will change RESP to point to the
-+ * structure return address. */
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
+
-+ ffi_prep_incoming_args(args, respp, arg_area, cif);
++#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
++/* This is a special case for mips64/n32 ABI (and perhaps others) where
++ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
++typedef union {
++ signed int sint;
++ unsigned int uint;
++ float flt;
++ char data[FFI_SIZEOF_JAVA_RAW];
++ void* ptr;
++} ffi_java_raw;
++#else
++typedef ffi_raw ffi_java_raw;
++#endif
+
-+ (closure->fun) (cif, *respp, arg_area, closure->user_data);
+
-+ return cif->flags;
-+}
++void ffi_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_raw *avalue);
+
-+unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
-+ffi_closure_WIN32_inner (ffi_closure *closure, void **respp, void *args)
-+{
-+ /* our various things... */
-+ ffi_cif *cif;
-+ void **arg_area;
-+ unsigned int ret;
++void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
++void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
++size_t ffi_raw_size (ffi_cif *cif);
+
-+ cif = closure->cif;
-+ arg_area = (void**) alloca (cif->nargs * sizeof (void*));
++/* This is analogous to the raw API, except it uses Java parameter */
++/* packing, even on 64-bit machines. I.e. on 64-bit machines */
++/* longs and doubles are followed by an empty 64-bit word. */
+
-+ /* this call will initialize ARG_AREA, such that each
-+ * element in that array points to the corresponding
-+ * value on the stack; and if the function returns
-+ * a structure, it will change RESP to point to the
-+ * structure return address. */
++void ffi_java_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_java_raw *avalue);
+
-+ ret = ffi_prep_incoming_args(args, respp, arg_area, cif);
++void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
++void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
++size_t ffi_java_raw_size (ffi_cif *cif);
+
-+ (closure->fun) (cif, *respp, arg_area, closure->user_data);
++/* ---- Definitions for closures ----------------------------------------- */
+
-+ return ret;
-+}
-+#endif /* !X86_WIN64 */
++#if FFI_CLOSURES
+
-+static unsigned int
-+ffi_prep_incoming_args(char *stack, void **rvalue, void **avalue,
-+ ffi_cif *cif)
-+{
-+ register unsigned int i;
-+ register void **p_argv;
-+ register char *argp;
-+ register ffi_type **p_arg;
-+#ifndef X86_WIN64
-+ const int cabi = cif->abi;
-+ const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1;
-+ const unsigned int max_stack_count = (cabi == FFI_THISCALL) ? 1
-+ : (cabi == FFI_FASTCALL) ? 2
-+ : (cabi == FFI_REGISTER) ? 3
-+ : 0;
-+ unsigned int passed_regs = 0;
-+ void *p_stack_data[3] = { stack - 1 };
++#ifdef _MSC_VER
++__declspec(align(8))
++#endif
++typedef struct {
++#if 0
++ void *trampoline_table;
++ void *trampoline_table_entry;
+#else
-+ #define dir 1
++ char tramp[FFI_TRAMPOLINE_SIZE];
+#endif
-+
-+ argp = stack;
-+#ifndef X86_WIN64
-+ argp += max_stack_count * FFI_SIZEOF_ARG;
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void *user_data;
++#ifdef __GNUC__
++} ffi_closure __attribute__((aligned (8)));
++#else
++} ffi_closure;
++# ifdef __sgi
++# pragma pack 0
++# endif
+#endif
+
-+ if ((cif->flags == FFI_TYPE_STRUCT
-+ || cif->flags == FFI_TYPE_MS_STRUCT)
-+#ifdef X86_WIN64
-+ && ((cif->rtype->size & (1 | 2 | 4 | 8)) == 0)
-+#endif
-+ )
-+ {
-+#ifndef X86_WIN64
-+ if (passed_regs < max_stack_count)
-+ {
-+ *rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG));
-+ ++passed_regs;
-+ }
-+ else
-+#endif
-+ {
-+ *rvalue = *(void **) argp;
-+ argp += sizeof(void *);
-+ }
-+ }
++void *ffi_closure_alloc (size_t size, void **code);
++void ffi_closure_free (void *);
+
-+#ifndef X86_WIN64
-+ /* Do register arguments first */
-+ for (i = 0, p_arg = cif->arg_types;
-+ i < cif->nargs && passed_regs < max_stack_count;
-+ i++, p_arg++)
-+ {
-+ if ((*p_arg)->type == FFI_TYPE_FLOAT
-+ || (*p_arg)->type == FFI_TYPE_STRUCT)
-+ continue;
++ffi_status
++ffi_prep_closure (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data);
+
-+ size_t sz = (*p_arg)->size;
-+ if(sz == 0 || sz > FFI_SIZEOF_ARG)
-+ continue;
++ffi_status
++ffi_prep_closure_loc (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data,
++ void*codeloc);
+
-+ p_stack_data[passed_regs] = avalue + i;
-+ avalue[i] = stack + (passed_regs*FFI_SIZEOF_ARG);
-+ ++passed_regs;
-+ }
++#ifdef __sgi
++# pragma pack 8
++#endif
++typedef struct {
++#if 0
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
+#endif
++ ffi_cif *cif;
+
-+ p_arg = cif->arg_types;
-+ p_argv = avalue;
-+ if (dir < 0)
-+ {
-+ const int nargs = cif->nargs - 1;
-+ if (nargs > 0)
-+ {
-+ p_arg += nargs;
-+ p_argv += nargs;
-+ }
-+ }
++#if !FFI_NATIVE_RAW_API
+
-+ for (i = cif->nargs;
-+ i != 0;
-+ i--, p_arg += dir, p_argv += dir)
-+ {
-+ /* Align if necessary */
-+ if ((sizeof(void*) - 1) & (size_t) argp)
-+ argp = (char *) ALIGN(argp, sizeof(void*));
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+ size_t z = (*p_arg)->size;
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+#ifdef X86_WIN64
-+ if (z > FFI_SIZEOF_ARG
-+ || ((*p_arg)->type == FFI_TYPE_STRUCT
-+ && (z & (1 | 2 | 4 | 8)) == 0)
-+#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
-+ || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
+#endif
-+ )
-+ {
-+ z = FFI_SIZEOF_ARG;
-+ *p_argv = *(void **)argp;
-+ }
-+ else
++
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void *user_data;
++
++} ffi_raw_closure;
++
++typedef struct {
++#if 0
++ void *trampoline_table;
++ void *trampoline_table_entry;
+#else
-+ if (passed_regs > 0
-+ && z <= FFI_SIZEOF_ARG
-+ && (p_argv == p_stack_data[0]
-+ || p_argv == p_stack_data[1]
-+ || p_argv == p_stack_data[2]))
-+ {
-+ /* Already assigned a register value */
-+ continue;
-+ }
-+ else
++ char tramp[FFI_TRAMPOLINE_SIZE];
+#endif
-+ {
-+ /* because we're little endian, this is what it turns into. */
-+ *p_argv = (void*) argp;
-+ }
+
-+#ifdef X86_WIN64
-+ argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-+#else
-+ argp += z;
++ ffi_cif *cif;
++
++#if !FFI_NATIVE_RAW_API
++
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
++
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
++
+#endif
-+ }
+
-+ return (size_t)argp - (size_t)stack;
-+}
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
++ void *user_data;
+
-+#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
-+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-+ void* __fun = (void*)(FUN); \
-+ void* __ctx = (void*)(CTX); \
-+ *(unsigned char*) &__tramp[0] = 0x41; \
-+ *(unsigned char*) &__tramp[1] = 0xbb; \
-+ *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
-+ *(unsigned char*) &__tramp[6] = 0x48; \
-+ *(unsigned char*) &__tramp[7] = 0xb8; \
-+ *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
-+ *(unsigned char *) &__tramp[16] = 0x49; \
-+ *(unsigned char *) &__tramp[17] = 0xba; \
-+ *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
-+ *(unsigned char *) &__tramp[26] = 0x41; \
-+ *(unsigned char *) &__tramp[27] = 0xff; \
-+ *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
-+ }
-+
-+/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
-+
-+#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
-+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-+ unsigned int __fun = (unsigned int)(FUN); \
-+ unsigned int __ctx = (unsigned int)(CTX); \
-+ unsigned int __dis = __fun - (__ctx + 10); \
-+ *(unsigned char*) &__tramp[0] = 0xb8; \
-+ *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
-+ *(unsigned char*) &__tramp[5] = 0xe9; \
-+ *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
-+ }
-+
-+#define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \
-+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-+ unsigned int __fun = (unsigned int)(FUN); \
-+ unsigned int __ctx = (unsigned int)(CTX); \
-+ unsigned int __dis = __fun - (__ctx + 49); \
-+ unsigned short __size = (unsigned short)(SIZE); \
-+ *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
-+ *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
-+ *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
-+ *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
-+ *(unsigned char*) &__tramp[13] = 0xb8; \
-+ *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
-+ *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
-+ *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
-+ *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
-+ *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
-+ *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
-+ *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
-+ *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
-+ *(unsigned char*) &__tramp[39] = 0xb8; \
-+ *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
-+ *(unsigned char *) &__tramp[44] = 0xe8; \
-+ *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
-+ *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
-+ *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
-+ }
-+
-+#define FFI_INIT_TRAMPOLINE_WIN32(TRAMP,FUN,CTX) \
-+{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-+ unsigned int __fun = (unsigned int)(FUN); \
-+ unsigned int __ctx = (unsigned int)(CTX); \
-+ unsigned int __dis = __fun - (__ctx + 10); \
-+ *(unsigned char*) &__tramp[0] = 0x68; \
-+ *(unsigned int*) &__tramp[1] = __ctx; /* push __ctx */ \
-+ *(unsigned char*) &__tramp[5] = 0xe9; \
-+ *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
-+ }
++} ffi_java_raw_closure;
+
-+/* the cif must already be prep'ed */
++ffi_status
++ffi_prep_raw_closure (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data);
+
+ffi_status
-+ffi_prep_closure_loc (ffi_closure* closure,
-+ ffi_cif* cif,
-+ void (*fun)(ffi_cif*,void*,void**,void*),
-+ void *user_data,
-+ void *codeloc)
-+{
-+#ifdef X86_WIN64
-+#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
-+#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
-+ if (cif->abi == FFI_WIN64)
-+ {
-+ int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
-+ FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
-+ &ffi_closure_win64,
-+ codeloc, mask);
-+ /* make sure we can execute here */
-+ }
-+#else
-+ if (cif->abi == FFI_SYSV)
-+ {
-+ FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-+ &ffi_closure_SYSV,
-+ (void*)codeloc);
-+ }
-+ else if (cif->abi == FFI_REGISTER)
-+ {
-+ FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-+ &ffi_closure_REGISTER,
-+ (void*)codeloc);
-+ }
-+ else if (cif->abi == FFI_FASTCALL)
-+ {
-+ FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-+ &ffi_closure_FASTCALL,
-+ (void*)codeloc);
-+ }
-+ else if (cif->abi == FFI_THISCALL)
-+ {
-+ FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-+ &ffi_closure_THISCALL,
-+ (void*)codeloc);
-+ }
-+ else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL)
-+ {
-+ FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
-+ &ffi_closure_STDCALL,
-+ (void*)codeloc);
-+ }
-+#ifdef X86_WIN32
-+ else if (cif->abi == FFI_MS_CDECL)
-+ {
-+ FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-+ &ffi_closure_SYSV,
-+ (void*)codeloc);
-+ }
-+#endif /* X86_WIN32 */
-+#endif /* !X86_WIN64 */
-+ else
-+ {
-+ return FFI_BAD_ABI;
-+ }
-+
-+ closure->cif = cif;
-+ closure->user_data = user_data;
-+ closure->fun = fun;
++ffi_prep_raw_closure_loc (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+ return FFI_OK;
-+}
++ffi_status
++ffi_prep_java_raw_closure (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data);
+
-+/* ------- Native raw API support -------------------------------- */
++ffi_status
++ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+#if !FFI_NO_RAW_API
++#endif /* FFI_CLOSURES */
+
-+ffi_status
-+ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
-+ ffi_cif* cif,
-+ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
-+ void *user_data,
-+ void *codeloc)
-+{
-+ int i;
++#if FFI_GO_CLOSURES
+
-+ if (cif->abi != FFI_SYSV
-+#ifdef X86_WIN32
-+ && cif->abi != FFI_THISCALL
-+#endif
-+ )
-+ return FFI_BAD_ABI;
++typedef struct {
++ void *tramp;
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++} ffi_go_closure;
+
-+ /* we currently don't support certain kinds of arguments for raw
-+ closures. This should be implemented by a separate assembly
-+ language routine, since it would require argument processing,
-+ something we don't do now for performance. */
++ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*));
+
-+ for (i = cif->nargs-1; i >= 0; i--)
-+ {
-+ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
-+ FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
-+ }
-+
-+#ifdef X86_WIN32
-+ if (cif->abi == FFI_SYSV)
-+ {
-+#endif
-+ FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
-+ codeloc);
-+#ifdef X86_WIN32
-+ }
-+ else if (cif->abi == FFI_THISCALL)
-+ {
-+ FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, codeloc, cif->bytes);
-+ }
-+#endif
-+ closure->cif = cif;
-+ closure->user_data = user_data;
-+ closure->fun = fun;
++void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
++ void **avalue, void *closure);
+
-+ return FFI_OK;
-+}
++#endif /* FFI_GO_CLOSURES */
+
-+static unsigned int
-+ffi_prep_args_raw(char *stack, extended_cif *ecif)
-+{
-+ const ffi_cif *cif = ecif->cif;
-+ unsigned int i, passed_regs = 0;
-+
-+#ifndef X86_WIN64
-+ const unsigned int abi = cif->abi;
-+ const unsigned int max_regs = (abi == FFI_THISCALL) ? 1
-+ : (abi == FFI_FASTCALL) ? 2
-+ : (abi == FFI_REGISTER) ? 3
-+ : 0;
-+
-+ if (cif->flags == FFI_TYPE_STRUCT)
-+ ++passed_regs;
-+
-+ for (i = 0; i < cif->nargs && passed_regs <= max_regs; i++)
-+ {
-+ if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
-+ || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
-+ continue;
++/* ---- Public interface definition -------------------------------------- */
+
-+ size_t sz = cif->arg_types[i]->size;
-+ if (sz == 0 || sz > FFI_SIZEOF_ARG)
-+ continue;
++ffi_status ffi_prep_cif(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ ++passed_regs;
-+ }
-+#endif
++ffi_status ffi_prep_cif_var(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+ memcpy (stack, ecif->avalue, cif->bytes);
-+ return passed_regs;
-+}
++void ffi_call(ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ void **avalue);
+
-+/* we borrow this routine from libffi (it must be changed, though, to
-+ * actually call the function passed in the first argument. as of
-+ * libffi-1.20, this is not the case.)
-+ */
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
+
-+void
-+ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
-+{
-+ extended_cif ecif;
-+ void **avalue = (void **)fake_avalue;
++/* ---- Definitions shared with assembly code ---------------------------- */
+
-+ ecif.cif = cif;
-+ ecif.avalue = avalue;
-+
-+ /* If the return value is a struct and we don't have a return */
-+ /* value address then we need to make one */
++#endif
+
-+ if (rvalue == NULL
-+ && (cif->flags == FFI_TYPE_STRUCT
-+ || cif->flags == FFI_TYPE_MS_STRUCT))
-+ {
-+ ecif.rvalue = alloca(cif->rtype->size);
-+ }
-+ else
-+ ecif.rvalue = rvalue;
-+
-+
-+ switch (cif->abi)
-+ {
-+#ifndef X86_WIN32
-+ case FFI_SYSV:
-+ ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
-+ ecif.rvalue, fn);
-+ break;
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++#if 1
++#define FFI_TYPE_LONGDOUBLE 4
+#else
-+ case FFI_SYSV:
-+ case FFI_MS_CDECL:
-+#endif
-+#ifndef X86_WIN64
-+ case FFI_STDCALL:
-+ case FFI_THISCALL:
-+ case FFI_FASTCALL:
-+ case FFI_PASCAL:
-+ case FFI_REGISTER:
-+ ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
-+ ecif.rvalue, fn);
-+ break;
++#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
+#endif
-+ default:
-+ FFI_ASSERT(0);
-+ break;
-+ }
-+}
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++#define FFI_TYPE_COMPLEX 15
+
-+#endif
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
+
-+#endif /* !__x86_64__ || X86_WIN64 */
++#ifdef __cplusplus
++}
++#endif
+
++#endif
+
+
+#endif
\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios/x86/win32_i386.S modified/Modules/_ctypes/libffi_ios/x86/win32_i386.S
---- orig/Modules/_ctypes/libffi_ios/x86/win32_i386.S 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios/x86/win32_i386.S 2015-04-26 08:18:45.000000000 +0800
-@@ -0,0 +1,1356 @@
-+#ifdef __i386__
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h modified/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h
+--- orig/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/ffi_x86_64.h 2015-12-20 18:55:29.000000000 +0800
+@@ -0,0 +1,508 @@
++#ifdef __x86_64__
+
-+/* -----------------------------------------------------------------------
-+ win32.S - Copyright (c) 2014 Anthony Green
-+ Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc.
-+ Copyright (c) 2001 John Beniton
-+ Copyright (c) 2002 Ranjit Mathew
-+ Copyright (c) 2009 Daniel Witte
++/* -----------------------------------------------------------------*-C-*-
++ libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green
++ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
++
++ Permission is hereby granted, free of charge, to any person
++ obtaining a copy of this software and associated documentation
++ files (the ``Software''), to deal in the Software without
++ restriction, including without limitation the rights to use, copy,
++ modify, merge, publish, distribute, sublicense, and/or sell copies
++ of the Software, and to permit persons to whom the Software is
++ furnished to do so, subject to the following conditions:
+
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
+
-+ X86 Foreign Function Interface
-+
-+ Permission is hereby granted, free of charge, to any person obtaining
-+ a copy of this software and associated documentation files (the
-+ ``Software''), to deal in the Software without restriction, including
-+ without limitation the rights to use, copy, modify, merge, publish,
-+ distribute, sublicense, and/or sell copies of the Software, and to
-+ permit persons to whom the Software is furnished to do so, subject to
-+ the following conditions:
-+
-+ The above copyright notice and this permission notice shall be included
-+ in all copies or substantial portions of the Software.
-+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -32905,5308 +24765,3755 @@ diff -Nru orig/Modules/_ctypes/libffi_ios/x86/win32_i386.S modified/Modules/_cty
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
-+ -----------------------------------------------------------------------
-+ */
-+
-+#define LIBFFI_ASM
-+#include
-+#include
+
-+#define CIF_BYTES_OFFSET 16
-+#define CIF_FLAGS_OFFSET 20
++ ----------------------------------------------------------------------- */
+
-+#ifdef _MSC_VER
++/* -------------------------------------------------------------------
++ The basic API is described in the README file.
+
-+#define CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
-+
-+.386
-+.MODEL FLAT, C
-+
-+EXTRN ffi_closure_SYSV_inner:NEAR
-+EXTRN ffi_closure_WIN32_inner:NEAR
-+
-+_TEXT SEGMENT
-+
-+ffi_call_win32 PROC NEAR,
-+ ffi_prep_args : NEAR PTR DWORD,
-+ ecif : NEAR PTR DWORD,
-+ cif_abi : DWORD,
-+ cif_bytes : DWORD,
-+ cif_flags : DWORD,
-+ rvalue : NEAR PTR DWORD,
-+ fn : NEAR PTR DWORD
-+
-+ ;; Make room for all of the new args.
-+ mov ecx, cif_bytes
-+ sub esp, ecx
-+
-+ mov eax, esp
-+
-+ ;; Call ffi_prep_args
-+ push ecif
-+ push eax
-+ call ffi_prep_args
-+ add esp, 8
-+
-+ ;; Prepare registers
-+ ;; EAX stores the number of register arguments
-+ cmp eax, 0
-+ je fun
-+ cmp eax, 3
-+ jl prepr_two_cmp
-+
-+ mov ecx, esp
-+ add esp, 12
-+ mov eax, DWORD PTR [ecx+8]
-+ jmp prepr_two
-+prepr_two_cmp:
-+ cmp eax, 2
-+ jl prepr_one_prep
-+ mov ecx, esp
-+ add esp, 8
-+prepr_two:
-+ mov edx, DWORD PTR [ecx+4]
-+ jmp prepr_one
-+prepr_one_prep:
-+ mov ecx, esp
-+ add esp, 4
-+prepr_one:
-+ mov ecx, DWORD PTR [ecx]
-+ cmp cif_abi, 7 ;; FFI_REGISTER
-+ jne fun
-+
-+ xchg ecx, eax
-+
-+fun:
-+ ;; Call function
-+ call fn
-+
-+ ;; Load ecx with the return type code
-+ mov ecx, cif_flags
-+
-+ ;; If the return value pointer is NULL, assume no return value.
-+ cmp rvalue, 0
-+ jne ca_jumptable
-+
-+ ;; Even if there is no space for the return value, we are
-+ ;; obliged to handle floating-point values.
-+ cmp ecx, FFI_TYPE_FLOAT
-+ jne ca_epilogue
-+ fstp st(0)
-+
-+ jmp ca_epilogue
-+
-+ca_jumptable:
-+ jmp [ca_jumpdata + 4 * ecx]
-+ca_jumpdata:
-+ ;; Do not insert anything here between label and jump table.
-+ dd offset ca_epilogue ;; FFI_TYPE_VOID
-+ dd offset ca_retint ;; FFI_TYPE_INT
-+ dd offset ca_retfloat ;; FFI_TYPE_FLOAT
-+ dd offset ca_retdouble ;; FFI_TYPE_DOUBLE
-+ dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE
-+ dd offset ca_retuint8 ;; FFI_TYPE_UINT8
-+ dd offset ca_retsint8 ;; FFI_TYPE_SINT8
-+ dd offset ca_retuint16 ;; FFI_TYPE_UINT16
-+ dd offset ca_retsint16 ;; FFI_TYPE_SINT16
-+ dd offset ca_retint ;; FFI_TYPE_UINT32
-+ dd offset ca_retint ;; FFI_TYPE_SINT32
-+ dd offset ca_retint64 ;; FFI_TYPE_UINT64
-+ dd offset ca_retint64 ;; FFI_TYPE_SINT64
-+ dd offset ca_epilogue ;; FFI_TYPE_STRUCT
-+ dd offset ca_retint ;; FFI_TYPE_POINTER
-+ dd offset ca_retstruct1b ;; FFI_TYPE_SMALL_STRUCT_1B
-+ dd offset ca_retstruct2b ;; FFI_TYPE_SMALL_STRUCT_2B
-+ dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B
-+ dd offset ca_epilogue ;; FFI_TYPE_MS_STRUCT
-+
-+ /* Sign/zero extend as appropriate. */
-+ca_retuint8:
-+ movzx eax, al
-+ jmp ca_retint
-+
-+ca_retsint8:
-+ movsx eax, al
-+ jmp ca_retint
-+
-+ca_retuint16:
-+ movzx eax, ax
-+ jmp ca_retint
-+
-+ca_retsint16:
-+ movsx eax, ax
-+ jmp ca_retint
-+
-+ca_retint:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ mov [ecx + 0], eax
-+ jmp ca_epilogue
-+
-+ca_retint64:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ mov [ecx + 0], eax
-+ mov [ecx + 4], edx
-+ jmp ca_epilogue
-+
-+ca_retfloat:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ fstp DWORD PTR [ecx]
-+ jmp ca_epilogue
-+
-+ca_retdouble:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ fstp QWORD PTR [ecx]
-+ jmp ca_epilogue
-+
-+ca_retlongdouble:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ fstp TBYTE PTR [ecx]
-+ jmp ca_epilogue
-+
-+ca_retstruct1b:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ mov [ecx + 0], al
-+ jmp ca_epilogue
-+
-+ca_retstruct2b:
-+ ;; Load %ecx with the pointer to storage for the return value
-+ mov ecx, rvalue
-+ mov [ecx + 0], ax
-+ jmp ca_epilogue
-+
-+ca_epilogue:
-+ ;; Epilogue code is autogenerated.
-+ ret
-+ffi_call_win32 ENDP
-+
-+ffi_closure_THISCALL PROC NEAR
-+ ;; Insert the register argument on the stack as the first argument
-+ xchg DWORD PTR [esp+4], ecx
-+ xchg DWORD PTR [esp], ecx
-+ push ecx
-+ jmp ffi_closure_STDCALL
-+ffi_closure_THISCALL ENDP
-+
-+ffi_closure_FASTCALL PROC NEAR
-+ ;; Insert the 2 register arguments on the stack as the first argument
-+ xchg DWORD PTR [esp+4], edx
-+ xchg DWORD PTR [esp], ecx
-+ push edx
-+ push ecx
-+ jmp ffi_closure_STDCALL
-+ffi_closure_FASTCALL ENDP
-+
-+ffi_closure_REGISTER PROC NEAR
-+ ;; Insert the 3 register arguments on the stack as the first argument
-+ push eax
-+ xchg DWORD PTR [esp+8], ecx
-+ xchg DWORD PTR [esp+4], edx
-+ push ecx
-+ push edx
-+ jmp ffi_closure_STDCALL
-+ffi_closure_REGISTER ENDP
-+
-+ffi_closure_SYSV PROC NEAR FORCEFRAME
-+ ;; the ffi_closure ctx is passed in eax by the trampoline.
-+
-+ sub esp, 40
-+ lea edx, [ebp - 24]
-+ mov [ebp - 12], edx ;; resp
-+ lea edx, [ebp + 8]
-+stub::
-+ mov [esp + 8], edx ;; args
-+ lea edx, [ebp - 12]
-+ mov [esp + 4], edx ;; &resp
-+ mov [esp], eax ;; closure
-+ call ffi_closure_SYSV_inner
-+ mov ecx, [ebp - 12]
-+
-+cs_jumptable:
-+ jmp [cs_jumpdata + 4 * eax]
-+cs_jumpdata:
-+ ;; Do not insert anything here between the label and jump table.
-+ dd offset cs_epilogue ;; FFI_TYPE_VOID
-+ dd offset cs_retint ;; FFI_TYPE_INT
-+ dd offset cs_retfloat ;; FFI_TYPE_FLOAT
-+ dd offset cs_retdouble ;; FFI_TYPE_DOUBLE
-+ dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE
-+ dd offset cs_retuint8 ;; FFI_TYPE_UINT8
-+ dd offset cs_retsint8 ;; FFI_TYPE_SINT8
-+ dd offset cs_retuint16 ;; FFI_TYPE_UINT16
-+ dd offset cs_retsint16 ;; FFI_TYPE_SINT16
-+ dd offset cs_retint ;; FFI_TYPE_UINT32
-+ dd offset cs_retint ;; FFI_TYPE_SINT32
-+ dd offset cs_retint64 ;; FFI_TYPE_UINT64
-+ dd offset cs_retint64 ;; FFI_TYPE_SINT64
-+ dd offset cs_retstruct ;; FFI_TYPE_STRUCT
-+ dd offset cs_retint ;; FFI_TYPE_POINTER
-+ dd offset cs_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
-+ dd offset cs_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
-+ dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B
-+ dd offset cs_retmsstruct ;; FFI_TYPE_MS_STRUCT
-+
-+cs_retuint8:
-+ movzx eax, BYTE PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retsint8:
-+ movsx eax, BYTE PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retuint16:
-+ movzx eax, WORD PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retsint16:
-+ movsx eax, WORD PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retint:
-+ mov eax, [ecx]
-+ jmp cs_epilogue
-+
-+cs_retint64:
-+ mov eax, [ecx + 0]
-+ mov edx, [ecx + 4]
-+ jmp cs_epilogue
-+
-+cs_retfloat:
-+ fld DWORD PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retdouble:
-+ fld QWORD PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retlongdouble:
-+ fld TBYTE PTR [ecx]
-+ jmp cs_epilogue
-+
-+cs_retstruct:
-+ ;; Caller expects us to pop struct return value pointer hidden arg.
-+ ;; Epilogue code is autogenerated.
-+ ret 4
-+
-+cs_retmsstruct:
-+ ;; Caller expects us to return a pointer to the real return value.
-+ mov eax, ecx
-+ ;; Caller doesn't expects us to pop struct return value pointer hidden arg.
-+ jmp cs_epilogue
-+
-+cs_epilogue:
-+ ;; Epilogue code is autogenerated.
-+ ret
-+ffi_closure_SYSV ENDP
++ The raw API is designed to bypass some of the argument packing
++ and unpacking on architectures for which it can be avoided.
+
-+#if !FFI_NO_RAW_API
++ The closure API allows interpreted functions to be packaged up
++ inside a C function pointer, so that they can be called as C functions,
++ with no understanding on the client side that they are interpreted.
++ It can also be used in other cases in which it is necessary to package
++ up a user specified parameter and a function pointer as a single
++ function pointer.
++
++ The closure API must be implemented in order to get its functionality,
++ e.g. for use by gij. Routines are provided to emulate the raw API
++ if the underlying platform doesn't allow faster implementation.
+
-+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
-+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
-+
-+ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME
-+ sub esp, 36
-+ mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
-+ mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
-+ mov [esp + 12], edx
-+ lea edx, [ebp + 12]
-+ jmp stubraw
-+ffi_closure_raw_THISCALL ENDP
-+
-+ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME
-+ ;; the ffi_closure ctx is passed in eax by the trampoline.
-+
-+ sub esp, 40
-+ mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
-+ mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
-+ mov [esp + 12], edx ;; user_data
-+ lea edx, [ebp + 8]
-+stubraw::
-+ mov [esp + 8], edx ;; raw_args
-+ lea edx, [ebp - 24]
-+ mov [esp + 4], edx ;; &res
-+ mov [esp], esi ;; cif
-+ call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun
-+ mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags
-+ lea ecx, [ebp - 24]
-+
-+cr_jumptable:
-+ jmp [cr_jumpdata + 4 * eax]
-+cr_jumpdata:
-+ ;; Do not insert anything here between the label and jump table.
-+ dd offset cr_epilogue ;; FFI_TYPE_VOID
-+ dd offset cr_retint ;; FFI_TYPE_INT
-+ dd offset cr_retfloat ;; FFI_TYPE_FLOAT
-+ dd offset cr_retdouble ;; FFI_TYPE_DOUBLE
-+ dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE
-+ dd offset cr_retuint8 ;; FFI_TYPE_UINT8
-+ dd offset cr_retsint8 ;; FFI_TYPE_SINT8
-+ dd offset cr_retuint16 ;; FFI_TYPE_UINT16
-+ dd offset cr_retsint16 ;; FFI_TYPE_SINT16
-+ dd offset cr_retint ;; FFI_TYPE_UINT32
-+ dd offset cr_retint ;; FFI_TYPE_SINT32
-+ dd offset cr_retint64 ;; FFI_TYPE_UINT64
-+ dd offset cr_retint64 ;; FFI_TYPE_SINT64
-+ dd offset cr_epilogue ;; FFI_TYPE_STRUCT
-+ dd offset cr_retint ;; FFI_TYPE_POINTER
-+ dd offset cr_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
-+ dd offset cr_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
-+ dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B
-+ dd offset cr_epilogue ;; FFI_TYPE_MS_STRUCT
-+
-+cr_retuint8:
-+ movzx eax, BYTE PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_retsint8:
-+ movsx eax, BYTE PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_retuint16:
-+ movzx eax, WORD PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_retsint16:
-+ movsx eax, WORD PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_retint:
-+ mov eax, [ecx]
-+ jmp cr_epilogue
-+
-+cr_retint64:
-+ mov eax, [ecx + 0]
-+ mov edx, [ecx + 4]
-+ jmp cr_epilogue
-+
-+cr_retfloat:
-+ fld DWORD PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_retdouble:
-+ fld QWORD PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_retlongdouble:
-+ fld TBYTE PTR [ecx]
-+ jmp cr_epilogue
-+
-+cr_epilogue:
-+ ;; Epilogue code is autogenerated.
-+ ret
-+ffi_closure_raw_SYSV ENDP
++ More details on the raw and cloure API can be found in:
+
-+#endif /* !FFI_NO_RAW_API */
++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
+
-+ffi_closure_STDCALL PROC NEAR FORCEFRAME
-+ mov eax, [esp] ;; the ffi_closure ctx passed by the trampoline.
-+
-+ sub esp, 40
-+ lea edx, [ebp - 24]
-+ mov [ebp - 12], edx ;; resp
-+ lea edx, [ebp + 12] ;; account for stub return address on stack
-+ mov [esp + 8], edx ;; args
-+ lea edx, [ebp - 12]
-+ mov [esp + 4], edx ;; &resp
-+ mov [esp], eax ;; closure
-+ call ffi_closure_WIN32_inner
-+ mov ecx, [ebp - 12]
-+
-+ xchg [ebp + 4], eax ;;xchg size of stack parameters and ffi_closure ctx
-+ mov eax, DWORD PTR [eax + CLOSURE_CIF_OFFSET]
-+ mov eax, DWORD PTR [eax + CIF_FLAGS_OFFSET]
-+
-+cd_jumptable:
-+ jmp [cd_jumpdata + 4 * eax]
-+cd_jumpdata:
-+ ;; Do not insert anything here between the label and jump table.
-+ dd offset cd_epilogue ;; FFI_TYPE_VOID
-+ dd offset cd_retint ;; FFI_TYPE_INT
-+ dd offset cd_retfloat ;; FFI_TYPE_FLOAT
-+ dd offset cd_retdouble ;; FFI_TYPE_DOUBLE
-+ dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE
-+ dd offset cd_retuint8 ;; FFI_TYPE_UINT8
-+ dd offset cd_retsint8 ;; FFI_TYPE_SINT8
-+ dd offset cd_retuint16 ;; FFI_TYPE_UINT16
-+ dd offset cd_retsint16 ;; FFI_TYPE_SINT16
-+ dd offset cd_retint ;; FFI_TYPE_UINT32
-+ dd offset cd_retint ;; FFI_TYPE_SINT32
-+ dd offset cd_retint64 ;; FFI_TYPE_UINT64
-+ dd offset cd_retint64 ;; FFI_TYPE_SINT64
-+ dd offset cd_epilogue ;; FFI_TYPE_STRUCT
-+ dd offset cd_retint ;; FFI_TYPE_POINTER
-+ dd offset cd_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
-+ dd offset cd_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
-+ dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B
-+
-+cd_retuint8:
-+ movzx eax, BYTE PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_retsint8:
-+ movsx eax, BYTE PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_retuint16:
-+ movzx eax, WORD PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_retsint16:
-+ movsx eax, WORD PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_retint:
-+ mov eax, [ecx]
-+ jmp cd_epilogue
-+
-+cd_retint64:
-+ mov eax, [ecx + 0]
-+ mov edx, [ecx + 4]
-+ jmp cd_epilogue
-+
-+cd_retfloat:
-+ fld DWORD PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_retdouble:
-+ fld QWORD PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_retlongdouble:
-+ fld TBYTE PTR [ecx]
-+ jmp cd_epilogue
-+
-+cd_epilogue:
-+ mov esp, ebp
-+ pop ebp
-+ mov ecx, [esp + 4] ;; Return address
-+ add esp, [esp] ;; Parameters stack size
-+ add esp, 8
-+ jmp ecx
-+ffi_closure_STDCALL ENDP
-+
-+_TEXT ENDS
-+END
++ and
+
-+#else
++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
++ -------------------------------------------------------------------- */
+
-+#define CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
++#ifndef LIBFFI_H
++#define LIBFFI_H
+
-+#if defined(SYMBOL_UNDERSCORE)
-+#define USCORE_SYMBOL(x) _##x
-+#else
-+#define USCORE_SYMBOL(x) x
++#ifdef __cplusplus
++extern "C" {
+#endif
-+ .text
-+
-+ # This assumes we are using gas.
-+ .balign 16
-+FFI_HIDDEN(ffi_call_win32)
-+ .globl USCORE_SYMBOL(ffi_call_win32)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_call_win32; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_call_win32):
-+.LFB1:
-+ pushl %ebp
-+.LCFI0:
-+ movl %esp,%ebp
-+.LCFI1:
-+ # Make room for all of the new args.
-+ movl 20(%ebp),%ecx
-+ subl %ecx,%esp
-+
-+ movl %esp,%eax
-+
-+ # Call ffi_prep_args
-+ pushl 12(%ebp)
-+ pushl %eax
-+ call *8(%ebp)
-+ addl $8,%esp
-+
-+ # Prepare registers
-+ # EAX stores the number of register arguments
-+ cmpl $0, %eax
-+ je .fun
-+ cmpl $3, %eax
-+ jl .prepr_two_cmp
-+
-+ movl %esp, %ecx
-+ addl $12, %esp
-+ movl 8(%ecx), %eax
-+ jmp .prepr_two
-+.prepr_two_cmp:
-+ cmpl $2, %eax
-+ jl .prepr_one_prep
-+ movl %esp, %ecx
-+ addl $8, %esp
-+.prepr_two:
-+ movl 4(%ecx), %edx
-+ jmp .prepr_one
-+.prepr_one_prep:
-+ movl %esp, %ecx
-+ addl $4, %esp
-+.prepr_one:
-+ movl (%ecx), %ecx
-+ cmpl $7, 16(%ebp) # FFI_REGISTER
-+ jne .fun
-+
-+ xchgl %eax, %ecx
-+
-+.fun:
-+ # FIXME: Align the stack to a 128-bit boundary to avoid
-+ # potential performance hits.
-+
-+ # Call function
-+ call *32(%ebp)
-+
-+ # stdcall functions pop arguments off the stack themselves
+
-+ # Load %ecx with the return type code
-+ movl 24(%ebp),%ecx
-+
-+ # If the return value pointer is NULL, assume no return value.
-+ cmpl $0,28(%ebp)
-+ jne 0f
-+
-+ # Even if there is no space for the return value, we are
-+ # obliged to handle floating-point values.
-+ cmpl $FFI_TYPE_FLOAT,%ecx
-+ jne .Lnoretval
-+ fstp %st(0)
-+
-+ jmp .Lepilogue
++/* Specify which architecture libffi is configured for. */
++#ifndef X86_64
++#define X86_64
++#endif
+
-+0:
-+ call 1f
-+ # Do not insert anything here between the call and the jump table.
-+.Lstore_table:
-+ .long .Lnoretval-.Lstore_table /* FFI_TYPE_VOID */
-+ .long .Lretint-.Lstore_table /* FFI_TYPE_INT */
-+ .long .Lretfloat-.Lstore_table /* FFI_TYPE_FLOAT */
-+ .long .Lretdouble-.Lstore_table /* FFI_TYPE_DOUBLE */
-+ .long .Lretlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */
-+ .long .Lretuint8-.Lstore_table /* FFI_TYPE_UINT8 */
-+ .long .Lretsint8-.Lstore_table /* FFI_TYPE_SINT8 */
-+ .long .Lretuint16-.Lstore_table /* FFI_TYPE_UINT16 */
-+ .long .Lretsint16-.Lstore_table /* FFI_TYPE_SINT16 */
-+ .long .Lretint-.Lstore_table /* FFI_TYPE_UINT32 */
-+ .long .Lretint-.Lstore_table /* FFI_TYPE_SINT32 */
-+ .long .Lretint64-.Lstore_table /* FFI_TYPE_UINT64 */
-+ .long .Lretint64-.Lstore_table /* FFI_TYPE_SINT64 */
-+ .long .Lretstruct-.Lstore_table /* FFI_TYPE_STRUCT */
-+ .long .Lretint-.Lstore_table /* FFI_TYPE_POINTER */
-+ .long .Lretstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */
-+ .long .Lretstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */
-+ .long .Lretstruct4b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_4B */
-+ .long .Lretstruct-.Lstore_table /* FFI_TYPE_MS_STRUCT */
-+1:
-+ shl $2, %ecx
-+ add (%esp),%ecx
-+ mov (%ecx),%ecx
-+ add (%esp),%ecx
-+ add $4, %esp
-+ jmp *%ecx
-+
-+ /* Sign/zero extend as appropriate. */
-+.Lretsint8:
-+ movsbl %al, %eax
-+ jmp .Lretint
-+
-+.Lretsint16:
-+ movswl %ax, %eax
-+ jmp .Lretint
-+
-+.Lretuint8:
-+ movzbl %al, %eax
-+ jmp .Lretint
-+
-+.Lretuint16:
-+ movzwl %ax, %eax
-+ jmp .Lretint
-+
-+.Lretint:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ movl %eax,0(%ecx)
-+ jmp .Lepilogue
-+
-+.Lretfloat:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ fstps (%ecx)
-+ jmp .Lepilogue
-+
-+.Lretdouble:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ fstpl (%ecx)
-+ jmp .Lepilogue
-+
-+.Lretlongdouble:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ fstpt (%ecx)
-+ jmp .Lepilogue
-+
-+.Lretint64:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ movl %eax,0(%ecx)
-+ movl %edx,4(%ecx)
-+ jmp .Lepilogue
-+
-+.Lretstruct1b:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ movb %al,0(%ecx)
-+ jmp .Lepilogue
-+
-+.Lretstruct2b:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ movw %ax,0(%ecx)
-+ jmp .Lepilogue
-+
-+.Lretstruct4b:
-+ # Load %ecx with the pointer to storage for the return value
-+ movl 28(%ebp),%ecx
-+ movl %eax,0(%ecx)
-+ jmp .Lepilogue
-+
-+.Lretstruct:
-+ # Nothing to do!
-+
-+.Lnoretval:
-+.Lepilogue:
-+ movl %ebp,%esp
-+ popl %ebp
-+ ret
-+.ffi_call_win32_end:
-+ .balign 16
-+FFI_HIDDEN(ffi_closure_THISCALL)
-+ .globl USCORE_SYMBOL(ffi_closure_THISCALL)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_THISCALL):
-+ /* Insert the register argument on the stack as the first argument */
-+ xchg %ecx, 4(%esp)
-+ xchg %ecx, (%esp)
-+ push %ecx
-+ jmp .ffi_closure_STDCALL_internal
-+
-+ .balign 16
-+FFI_HIDDEN(ffi_closure_FASTCALL)
-+ .globl USCORE_SYMBOL(ffi_closure_FASTCALL)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_FASTCALL; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_FASTCALL):
-+ /* Insert the 2 register arguments on the stack as the first two arguments */
-+ xchg %edx, 4(%esp)
-+ xchg %ecx, (%esp)
-+ push %edx
-+ push %ecx
-+ jmp .ffi_closure_STDCALL_internal
-+FFI_HIDDEN(ffi_closure_REGISTER)
-+ .globl USCORE_SYMBOL(ffi_closure_REGISTER)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_REGISTER; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_REGISTER):
-+ /* Insert the 3 register arguments on the stack as the first two arguments */
-+ push %eax
-+ xchg %ecx, 8(%esp)
-+ xchg %edx, 4(%esp)
-+ push %ecx
-+ push %edx
-+ jmp .ffi_closure_STDCALL_internal
-+
-+.LFE1:
-+ # This assumes we are using gas.
-+ .balign 16
-+FFI_HIDDEN(ffi_closure_SYSV)
-+#if defined(X86_WIN32)
-+ .globl USCORE_SYMBOL(ffi_closure_SYSV)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_SYSV; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_SYSV):
-+#endif
-+.LFB3:
-+ pushl %ebp
-+.LCFI4:
-+ movl %esp, %ebp
-+.LCFI5:
-+ subl $40, %esp
-+ leal -24(%ebp), %edx
-+ movl %edx, -12(%ebp) /* resp */
-+ leal 8(%ebp), %edx
-+ movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
-+ leal -12(%ebp), %edx
-+ movl %edx, (%esp) /* &resp */
-+#if defined(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE) || !defined(__PIC__)
-+ call USCORE_SYMBOL(ffi_closure_SYSV_inner)
-+#elif defined(X86_DARWIN)
-+ calll L_ffi_closure_SYSV_inner$stub
-+#else
-+ movl %ebx, 8(%esp)
-+ call 1f
-+1: popl %ebx
-+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-+ call ffi_closure_SYSV_inner@PLT
-+ movl 8(%esp), %ebx
++/* ---- System configuration information --------------------------------- */
++
++#include
++
++#ifndef LIBFFI_ASM
++
++#if defined(_MSC_VER) && !defined(__clang__)
++#define __attribute__(X)
+#endif
-+ movl -12(%ebp), %ecx
+
-+0:
-+ call 1f
-+ # Do not insert anything here between the call and the jump table.
-+.Lcls_store_table:
-+ .long .Lcls_noretval-.Lcls_store_table /* FFI_TYPE_VOID */
-+ .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_INT */
-+ .long .Lcls_retfloat-.Lcls_store_table /* FFI_TYPE_FLOAT */
-+ .long .Lcls_retdouble-.Lcls_store_table /* FFI_TYPE_DOUBLE */
-+ .long .Lcls_retldouble-.Lcls_store_table /* FFI_TYPE_LONGDOUBLE */
-+ .long .Lcls_retuint8-.Lcls_store_table /* FFI_TYPE_UINT8 */
-+ .long .Lcls_retsint8-.Lcls_store_table /* FFI_TYPE_SINT8 */
-+ .long .Lcls_retuint16-.Lcls_store_table /* FFI_TYPE_UINT16 */
-+ .long .Lcls_retsint16-.Lcls_store_table /* FFI_TYPE_SINT16 */
-+ .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_UINT32 */
-+ .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_SINT32 */
-+ .long .Lcls_retllong-.Lcls_store_table /* FFI_TYPE_UINT64 */
-+ .long .Lcls_retllong-.Lcls_store_table /* FFI_TYPE_SINT64 */
-+ .long .Lcls_retstruct-.Lcls_store_table /* FFI_TYPE_STRUCT */
-+ .long .Lcls_retint-.Lcls_store_table /* FFI_TYPE_POINTER */
-+ .long .Lcls_retstruct1-.Lcls_store_table /* FFI_TYPE_SMALL_STRUCT_1B */
-+ .long .Lcls_retstruct2-.Lcls_store_table /* FFI_TYPE_SMALL_STRUCT_2B */
-+ .long .Lcls_retstruct4-.Lcls_store_table /* FFI_TYPE_SMALL_STRUCT_4B */
-+ .long .Lcls_retmsstruct-.Lcls_store_table /* FFI_TYPE_MS_STRUCT */
++#include
++#include
+
-+1:
-+ shl $2, %eax
-+ add (%esp),%eax
-+ mov (%eax),%eax
-+ add (%esp),%eax
-+ add $4, %esp
-+ jmp *%eax
-+
-+ /* Sign/zero extend as appropriate. */
-+.Lcls_retsint8:
-+ movsbl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retsint16:
-+ movswl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retuint8:
-+ movzbl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retuint16:
-+ movzwl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retint:
-+ movl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retfloat:
-+ flds (%ecx)
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retdouble:
-+ fldl (%ecx)
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retldouble:
-+ fldt (%ecx)
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retllong:
-+ movl (%ecx), %eax
-+ movl 4(%ecx), %edx
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retstruct1:
-+ movsbl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retstruct2:
-+ movswl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retstruct4:
-+ movl (%ecx), %eax
-+ jmp .Lcls_epilogue
-+
-+.Lcls_retstruct:
-+ # Caller expects us to pop struct return value pointer hidden arg.
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret $0x4
-+
-+.Lcls_retmsstruct:
-+ # Caller expects us to return a pointer to the real return value.
-+ mov %ecx, %eax
-+ # Caller doesn't expects us to pop struct return value pointer hidden arg.
-+ jmp .Lcls_epilogue
-+
-+.Lcls_noretval:
-+.Lcls_epilogue:
-+ movl %ebp, %esp
-+ popl %ebp
-+ ret
-+.ffi_closure_SYSV_end:
-+.LFE3:
++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
++ But we can find it either under the correct ANSI name, or under GNU
++ C's internal name. */
+
-+#if !FFI_NO_RAW_API
++#define FFI_64_BIT_MAX 9223372036854775807
+
-+#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
-+#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
-+#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
++#ifdef LONG_LONG_MAX
++# define FFI_LONG_LONG_MAX LONG_LONG_MAX
++#else
++# ifdef LLONG_MAX
++# define FFI_LONG_LONG_MAX LLONG_MAX
++# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif /* _AIX52 or newer */
++# else
++# ifdef __GNUC__
++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
++# endif
++# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
++# ifndef __PPC64__
++# if defined (__IBMC__) || defined (__IBMCPP__)
++# define FFI_LONG_LONG_MAX LONGLONG_MAX
++# endif
++# endif /* __PPC64__ */
++# undef FFI_64_BIT_MAX
++# define FFI_64_BIT_MAX 9223372036854775807LL
++# endif
++# endif
++#endif
+
-+#ifdef X86_WIN32
-+ .balign 16
-+FFI_HIDDEN(ffi_closure_raw_THISCALL)
-+ .globl USCORE_SYMBOL(ffi_closure_raw_THISCALL)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_raw_THISCALL):
-+ pushl %ebp
-+ movl %esp, %ebp
-+ pushl %esi
-+ subl $36, %esp
-+ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
-+ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-+ movl %edx, 12(%esp) /* user_data */
-+ leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */
-+ jmp .stubraw
-+#endif /* X86_WIN32 */
-+
-+ # This assumes we are using gas.
-+ .balign 16
-+#if defined(X86_WIN32)
-+ .globl USCORE_SYMBOL(ffi_closure_raw_SYSV)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_raw_SYSV):
-+#endif /* defined(X86_WIN32) */
-+.LFB4:
-+ pushl %ebp
-+.LCFI6:
-+ movl %esp, %ebp
-+.LCFI7:
-+ pushl %esi
-+.LCFI8:
-+ subl $36, %esp
-+ movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
-+ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
-+ movl %edx, 12(%esp) /* user_data */
-+ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
-+.stubraw:
-+ movl %edx, 8(%esp) /* raw_args */
-+ leal -24(%ebp), %edx
-+ movl %edx, 4(%esp) /* &res */
-+ movl %esi, (%esp) /* cif */
-+ call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
-+ movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
-+0:
-+ call 1f
-+ # Do not insert anything here between the call and the jump table.
-+.Lrcls_store_table:
-+ .long .Lrcls_noretval-.Lrcls_store_table /* FFI_TYPE_VOID */
-+ .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_INT */
-+ .long .Lrcls_retfloat-.Lrcls_store_table /* FFI_TYPE_FLOAT */
-+ .long .Lrcls_retdouble-.Lrcls_store_table /* FFI_TYPE_DOUBLE */
-+ .long .Lrcls_retldouble-.Lrcls_store_table /* FFI_TYPE_LONGDOUBLE */
-+ .long .Lrcls_retuint8-.Lrcls_store_table /* FFI_TYPE_UINT8 */
-+ .long .Lrcls_retsint8-.Lrcls_store_table /* FFI_TYPE_SINT8 */
-+ .long .Lrcls_retuint16-.Lrcls_store_table /* FFI_TYPE_UINT16 */
-+ .long .Lrcls_retsint16-.Lrcls_store_table /* FFI_TYPE_SINT16 */
-+ .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_UINT32 */
-+ .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_SINT32 */
-+ .long .Lrcls_retllong-.Lrcls_store_table /* FFI_TYPE_UINT64 */
-+ .long .Lrcls_retllong-.Lrcls_store_table /* FFI_TYPE_SINT64 */
-+ .long .Lrcls_retstruct-.Lrcls_store_table /* FFI_TYPE_STRUCT */
-+ .long .Lrcls_retint-.Lrcls_store_table /* FFI_TYPE_POINTER */
-+ .long .Lrcls_retstruct1-.Lrcls_store_table /* FFI_TYPE_SMALL_STRUCT_1B */
-+ .long .Lrcls_retstruct2-.Lrcls_store_table /* FFI_TYPE_SMALL_STRUCT_2B */
-+ .long .Lrcls_retstruct4-.Lrcls_store_table /* FFI_TYPE_SMALL_STRUCT_4B */
-+ .long .Lrcls_retstruct-.Lrcls_store_table /* FFI_TYPE_MS_STRUCT */
-+1:
-+ shl $2, %eax
-+ add (%esp),%eax
-+ mov (%eax),%eax
-+ add (%esp),%eax
-+ add $4, %esp
-+ jmp *%eax
-+
-+ /* Sign/zero extend as appropriate. */
-+.Lrcls_retsint8:
-+ movsbl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retsint16:
-+ movswl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retuint8:
-+ movzbl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retuint16:
-+ movzwl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retint:
-+ movl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retfloat:
-+ flds -24(%ebp)
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retdouble:
-+ fldl -24(%ebp)
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retldouble:
-+ fldt -24(%ebp)
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retllong:
-+ movl -24(%ebp), %eax
-+ movl -20(%ebp), %edx
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retstruct1:
-+ movsbl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retstruct2:
-+ movswl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retstruct4:
-+ movl -24(%ebp), %eax
-+ jmp .Lrcls_epilogue
-+
-+.Lrcls_retstruct:
-+ # Nothing to do!
-+
-+.Lrcls_noretval:
-+.Lrcls_epilogue:
-+ addl $36, %esp
-+ popl %esi
-+ popl %ebp
-+ ret
-+.ffi_closure_raw_SYSV_end:
-+.LFE4:
++/* The closure code assumes that this works on pointers, i.e. a size_t */
++/* can hold a pointer. */
+
-+#endif /* !FFI_NO_RAW_API */
++typedef struct _ffi_type
++{
++ size_t size;
++ unsigned short alignment;
++ unsigned short type;
++ struct _ffi_type **elements;
++} ffi_type;
+
-+ # This assumes we are using gas.
-+ .balign 16
-+FFI_HIDDEN(ffi_closure_STDCALL)
-+ .globl USCORE_SYMBOL(ffi_closure_STDCALL)
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .def _ffi_closure_STDCALL; .scl 2; .type 32; .endef
-+#endif
-+USCORE_SYMBOL(ffi_closure_STDCALL):
-+.ffi_closure_STDCALL_internal:
-+ /* ffi_closure ctx is at top of the stack */
-+ movl (%esp), %eax
-+.LFB5:
-+ pushl %ebp
-+.LCFI9:
-+ movl %esp, %ebp
-+.LCFI10:
-+ subl $40, %esp
-+ leal -24(%ebp), %edx
-+ movl %edx, -12(%ebp) /* resp */
-+ leal 12(%ebp), %edx /* account for stub return address on stack */
-+ movl %edx, 4(%esp) /* args */
-+ leal -12(%ebp), %edx
-+ movl %edx, (%esp) /* &resp */
-+#if defined(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE) || !defined(__PIC__)
-+ call USCORE_SYMBOL(ffi_closure_WIN32_inner)
-+#elif defined(X86_DARWIN)
-+ calll L_ffi_closure_WIN32_inner$stub
-+#else
-+ movl %ebx, 8(%esp)
-+ call 1f
-+1: popl %ebx
-+ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-+ call ffi_closure_WIN32_inner@PLT
-+ movl 8(%esp), %ebx
-+#endif
-+ movl -12(%ebp), %ecx
-+0:
-+ xchgl 4(%ebp), %eax /* xchg size of stack parameters and ffi_closure ctx */
-+ movl CLOSURE_CIF_OFFSET(%eax), %eax
-+ movl CIF_FLAGS_OFFSET(%eax), %eax
-+
-+ call 1f
-+ # Do not insert anything here between the call and the jump table.
-+.Lscls_store_table:
-+ .long .Lscls_noretval-.Lscls_store_table /* FFI_TYPE_VOID */
-+ .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_INT */
-+ .long .Lscls_retfloat-.Lscls_store_table /* FFI_TYPE_FLOAT */
-+ .long .Lscls_retdouble-.Lscls_store_table /* FFI_TYPE_DOUBLE */
-+ .long .Lscls_retldouble-.Lscls_store_table /* FFI_TYPE_LONGDOUBLE */
-+ .long .Lscls_retuint8-.Lscls_store_table /* FFI_TYPE_UINT8 */
-+ .long .Lscls_retsint8-.Lscls_store_table /* FFI_TYPE_SINT8 */
-+ .long .Lscls_retuint16-.Lscls_store_table /* FFI_TYPE_UINT16 */
-+ .long .Lscls_retsint16-.Lscls_store_table /* FFI_TYPE_SINT16 */
-+ .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_UINT32 */
-+ .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_SINT32 */
-+ .long .Lscls_retllong-.Lscls_store_table /* FFI_TYPE_UINT64 */
-+ .long .Lscls_retllong-.Lscls_store_table /* FFI_TYPE_SINT64 */
-+ .long .Lscls_retstruct-.Lscls_store_table /* FFI_TYPE_STRUCT */
-+ .long .Lscls_retint-.Lscls_store_table /* FFI_TYPE_POINTER */
-+ .long .Lscls_retstruct1-.Lscls_store_table /* FFI_TYPE_SMALL_STRUCT_1B */
-+ .long .Lscls_retstruct2-.Lscls_store_table /* FFI_TYPE_SMALL_STRUCT_2B */
-+ .long .Lscls_retstruct4-.Lscls_store_table /* FFI_TYPE_SMALL_STRUCT_4B */
-+1:
-+ shl $2, %eax
-+ add (%esp),%eax
-+ mov (%eax),%eax
-+ add (%esp),%eax
-+ add $4, %esp
-+ jmp *%eax
-+
-+ /* Sign/zero extend as appropriate. */
-+.Lscls_retsint8:
-+ movsbl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retsint16:
-+ movswl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retuint8:
-+ movzbl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retuint16:
-+ movzwl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retint:
-+ movl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retfloat:
-+ flds (%ecx)
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retdouble:
-+ fldl (%ecx)
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retldouble:
-+ fldt (%ecx)
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retllong:
-+ movl (%ecx), %eax
-+ movl 4(%ecx), %edx
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retstruct1:
-+ movsbl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retstruct2:
-+ movswl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retstruct4:
-+ movl (%ecx), %eax
-+ jmp .Lscls_epilogue
-+
-+.Lscls_retstruct:
-+ # Nothing to do!
-+
-+.Lscls_noretval:
-+.Lscls_epilogue:
-+ movl %ebp, %esp
-+ popl %ebp
-+ movl 4(%esp), %ecx /* Return address */
-+ addl (%esp), %esp /* Parameters stack size */
-+ addl $8, %esp
-+ jmp *%ecx
-+.ffi_closure_STDCALL_end:
-+.LFE5:
-+
-+#if defined(X86_DARWIN)
-+.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
-+L_ffi_closure_SYSV_inner$stub:
-+ .indirect_symbol _ffi_closure_SYSV_inner
-+ hlt ; hlt ; hlt ; hlt ; hlt
-+L_ffi_closure_WIN32_inner$stub:
-+ .indirect_symbol _ffi_closure_WIN32_inner
-+ hlt ; hlt ; hlt ; hlt ; hlt
-+#endif
-+
-+#if defined(X86_WIN32) && !defined(__OS2__)
-+ .section .eh_frame,"w"
-+#endif
-+.Lframe1:
-+.LSCIE1:
-+ .long .LECIE1-.LASCIE1 /* Length of Common Information Entry */
-+.LASCIE1:
-+ .long 0x0 /* CIE Identifier Tag */
-+ .byte 0x1 /* CIE Version */
-+#ifdef __PIC__
-+ .ascii "zR\0" /* CIE Augmentation */
++#ifndef LIBFFI_HIDE_BASIC_TYPES
++#if SCHAR_MAX == 127
++# define ffi_type_uchar ffi_type_uint8
++# define ffi_type_schar ffi_type_sint8
+#else
-+ .ascii "\0" /* CIE Augmentation */
++ #error "char size not supported"
+#endif
-+ .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
-+ .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
-+ .byte 0x8 /* CIE RA Column */
-+#ifdef __PIC__
-+ .byte 0x1 /* .uleb128 0x1; Augmentation size */
-+ .byte 0x1b /* FDE Encoding (pcrel sdata4) */
-+#endif
-+ .byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
-+ .byte 0x4 /* .uleb128 0x4 */
-+ .byte 0x4 /* .uleb128 0x4 */
-+ .byte 0x88 /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
-+ .byte 0x1 /* .uleb128 0x1 */
-+ .align 4
-+.LECIE1:
-+
-+.LSFDE1:
-+ .long .LEFDE1-.LASFDE1 /* FDE Length */
-+.LASFDE1:
-+ .long .LASFDE1-.Lframe1 /* FDE CIE offset */
-+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-+ .long .LFB1-. /* FDE initial location */
++
++#if SHRT_MAX == 32767
++# define ffi_type_ushort ffi_type_uint16
++# define ffi_type_sshort ffi_type_sint16
++#elif SHRT_MAX == 2147483647
++# define ffi_type_ushort ffi_type_uint32
++# define ffi_type_sshort ffi_type_sint32
+#else
-+ .long .LFB1
++ #error "short size not supported"
+#endif
-+ .long .LFE1-.LFB1 /* FDE address range */
-+#ifdef __PIC__
-+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
-+#endif
-+ /* DW_CFA_xxx CFI instructions go here. */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI0-.LFB1
-+ .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-+ .byte 0x8 /* .uleb128 0x8 */
-+ .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-+ .byte 0x2 /* .uleb128 0x2 */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI1-.LCFI0
-+ .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-+ .byte 0x5 /* .uleb128 0x5 */
-+
-+ /* End of DW_CFA_xxx CFI instructions. */
-+ .align 4
-+.LEFDE1:
-+
-+.LSFDE3:
-+ .long .LEFDE3-.LASFDE3 /* FDE Length */
-+.LASFDE3:
-+ .long .LASFDE3-.Lframe1 /* FDE CIE offset */
-+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-+ .long .LFB3-. /* FDE initial location */
++
++#if INT_MAX == 32767
++# define ffi_type_uint ffi_type_uint16
++# define ffi_type_sint ffi_type_sint16
++#elif INT_MAX == 2147483647
++# define ffi_type_uint ffi_type_uint32
++# define ffi_type_sint ffi_type_sint32
++#elif INT_MAX == 9223372036854775807
++# define ffi_type_uint ffi_type_uint64
++# define ffi_type_sint ffi_type_sint64
+#else
-+ .long .LFB3
-+#endif
-+ .long .LFE3-.LFB3 /* FDE address range */
-+#ifdef __PIC__
-+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
++ #error "int size not supported"
+#endif
-+ /* DW_CFA_xxx CFI instructions go here. */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI4-.LFB3
-+ .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-+ .byte 0x8 /* .uleb128 0x8 */
-+ .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-+ .byte 0x2 /* .uleb128 0x2 */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI5-.LCFI4
-+ .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-+ .byte 0x5 /* .uleb128 0x5 */
+
-+ /* End of DW_CFA_xxx CFI instructions. */
-+ .align 4
-+.LEFDE3:
-+
-+#if !FFI_NO_RAW_API
++#if LONG_MAX == 2147483647
++# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
++ #error "no 64-bit data type supported"
++# endif
++#elif LONG_MAX != FFI_64_BIT_MAX
++ #error "long size not supported"
++#endif
+
-+.LSFDE4:
-+ .long .LEFDE4-.LASFDE4 /* FDE Length */
-+.LASFDE4:
-+ .long .LASFDE4-.Lframe1 /* FDE CIE offset */
-+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-+ .long .LFB4-. /* FDE initial location */
++#if LONG_MAX == 2147483647
++# define ffi_type_ulong ffi_type_uint32
++# define ffi_type_slong ffi_type_sint32
++#elif LONG_MAX == FFI_64_BIT_MAX
++# define ffi_type_ulong ffi_type_uint64
++# define ffi_type_slong ffi_type_sint64
+#else
-+ .long .LFB4
-+#endif
-+ .long .LFE4-.LFB4 /* FDE address range */
-+#ifdef __PIC__
-+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
++ #error "long size not supported"
+#endif
-+ /* DW_CFA_xxx CFI instructions go here. */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI6-.LFB4
-+ .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-+ .byte 0x8 /* .uleb128 0x8 */
-+ .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-+ .byte 0x2 /* .uleb128 0x2 */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI7-.LCFI6
-+ .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-+ .byte 0x5 /* .uleb128 0x5 */
+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI8-.LCFI7
-+ .byte 0x86 /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
-+ .byte 0x3 /* .uleb128 0x3 */
-+
-+ /* End of DW_CFA_xxx CFI instructions. */
-+ .align 4
-+.LEFDE4:
-+
-+#endif /* !FFI_NO_RAW_API */
-+
-+.LSFDE5:
-+ .long .LEFDE5-.LASFDE5 /* FDE Length */
-+.LASFDE5:
-+ .long .LASFDE5-.Lframe1 /* FDE CIE offset */
-+#if defined __PIC__ && defined HAVE_AS_X86_PCREL
-+ .long .LFB5-. /* FDE initial location */
++/* Need minimal decorations for DLLs to works on Windows. */
++/* GCC has autoimport and autoexport. Rely on Libtool to */
++/* help MSVC export from a DLL, but always declare data */
++/* to be imported for MSVC clients. This costs an extra */
++/* indirection for MSVC clients using the static version */
++/* of the library, but don't worry about that. Besides, */
++/* as a workaround, they can define FFI_BUILDING if they */
++/* *know* they are going to link with the static library. */
++#if defined _MSC_VER && !defined FFI_BUILDING
++#define FFI_EXTERN extern __declspec(dllimport)
+#else
-+ .long .LFB5
-+#endif
-+ .long .LFE5-.LFB5 /* FDE address range */
-+#ifdef __PIC__
-+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
++#define FFI_EXTERN extern
+#endif
-+ /* DW_CFA_xxx CFI instructions go here. */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI9-.LFB5
-+ .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
-+ .byte 0x8 /* .uleb128 0x8 */
-+ .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
-+ .byte 0x2 /* .uleb128 0x2 */
-+
-+ .byte 0x4 /* DW_CFA_advance_loc4 */
-+ .long .LCFI10-.LCFI9
-+ .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
-+ .byte 0x5 /* .uleb128 0x5 */
-+
-+ /* End of DW_CFA_xxx CFI instructions. */
-+ .align 4
-+.LEFDE5:
+
-+#endif /* !_MSC_VER */
++/* These are defined in types.c */
++FFI_EXTERN ffi_type ffi_type_void;
++FFI_EXTERN ffi_type ffi_type_uint8;
++FFI_EXTERN ffi_type ffi_type_sint8;
++FFI_EXTERN ffi_type ffi_type_uint16;
++FFI_EXTERN ffi_type ffi_type_sint16;
++FFI_EXTERN ffi_type ffi_type_uint32;
++FFI_EXTERN ffi_type ffi_type_sint32;
++FFI_EXTERN ffi_type ffi_type_uint64;
++FFI_EXTERN ffi_type ffi_type_sint64;
++FFI_EXTERN ffi_type ffi_type_float;
++FFI_EXTERN ffi_type ffi_type_double;
++FFI_EXTERN ffi_type ffi_type_pointer;
+
-+#if defined __ELF__ && defined __linux__
-+ .section .note.GNU-stack,"",@progbits
++#if 1
++FFI_EXTERN ffi_type ffi_type_longdouble;
++#else
++#define ffi_type_longdouble ffi_type_double
+#endif
+
-+
++#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
++FFI_EXTERN ffi_type ffi_type_complex_float;
++FFI_EXTERN ffi_type ffi_type_complex_double;
++#if 1
++FFI_EXTERN ffi_type ffi_type_complex_longdouble;
++#else
++#define ffi_type_complex_longdouble ffi_type_complex_double
+#endif
-\ No newline at end of file
-diff -Nru orig/Modules/_ctypes/libffi_ios_aarch64/LICENSE modified/Modules/_ctypes/libffi_ios_aarch64/LICENSE
---- orig/Modules/_ctypes/libffi_ios_aarch64/LICENSE 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios_aarch64/LICENSE 2015-02-26 10:00:15.000000000 +0800
-@@ -0,0 +1,21 @@
-+libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others.
-+See source files for details.
-+
-+Permission is hereby granted, free of charge, to any person obtaining
-+a copy of this software and associated documentation files (the
-+``Software''), to deal in the Software without restriction, including
-+without limitation the rights to use, copy, modify, merge, publish,
-+distribute, sublicense, and/or sell copies of the Software, and to
-+permit persons to whom the Software is furnished to do so, subject to
-+the following conditions:
-+
-+The above copyright notice and this permission notice shall be
-+included in all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-diff -Nru orig/Modules/_ctypes/libffi_ios_aarch64/README modified/Modules/_ctypes/libffi_ios_aarch64/README
---- orig/Modules/_ctypes/libffi_ios_aarch64/README 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios_aarch64/README 2015-04-26 08:51:27.000000000 +0800
-@@ -0,0 +1,450 @@
-+Status
-+======
-+
-+libffi-4?? was released on TBD. Check the libffi web
-+page for updates: .
-+
-+
-+What is libffi?
-+===============
-+
-+Compilers for high level languages generate code that follow certain
-+conventions. These conventions are necessary, in part, for separate
-+compilation to work. One such convention is the "calling
-+convention". The "calling convention" is essentially a set of
-+assumptions made by the compiler about where function arguments will
-+be found on entry to a function. A "calling convention" also specifies
-+where the return value for a function is found.
-+
-+Some programs may not know at the time of compilation what arguments
-+are to be passed to a function. For instance, an interpreter may be
-+told at run-time about the number and types of arguments used to call
-+a given function. Libffi can be used in such programs to provide a
-+bridge from the interpreter program to compiled code.
-+
-+The libffi library provides a portable, high level programming
-+interface to various calling conventions. This allows a programmer to
-+call any function specified by a call interface description at run
-+time.
-+
-+FFI stands for Foreign Function Interface. A foreign function
-+interface is the popular name for the interface that allows code
-+written in one language to call code written in another language. The
-+libffi library really only provides the lowest, machine dependent
-+layer of a fully featured foreign function interface. A layer must
-+exist above libffi that handles type conversions for values passed
-+between the two languages.
-+
-+
-+Supported Platforms
-+===================
-+
-+Libffi has been ported to many different platforms.
-+For specific configuration details and testing status, please
-+refer to the wiki page here:
-+
-+ http://www.moxielogic.org/wiki/index.php?title=Libffi_3.2
-+
-+At the time of release, the following basic configurations have been
-+tested:
++#endif
++#endif /* LIBFFI_HIDE_BASIC_TYPES */
+
-+|-----------------+------------------+-------------------------|
-+| Architecture | Operating System | Compiler |
-+|-----------------+------------------+-------------------------|
-+| AArch64 (ARM64) | iOS | Clang |
-+| AArch64 | Linux | GCC |
-+| Alpha | Linux | GCC |
-+| Alpha | Tru64 | GCC |
-+| ARC | Linux | GCC |
-+| ARM | Linux | GCC |
-+| ARM | iOS | GCC |
-+| AVR32 | Linux | GCC |
-+| Blackfin | uClinux | GCC |
-+| HPPA | HPUX | GCC |
-+| IA-64 | Linux | GCC |
-+| M68K | FreeMiNT | GCC |
-+| M68K | Linux | GCC |
-+| M68K | RTEMS | GCC |
-+| M88K | OpenBSD/mvme88k | GCC |
-+| Meta | Linux | GCC |
-+| MicroBlaze | Linux | GCC |
-+| MIPS | IRIX | GCC |
-+| MIPS | Linux | GCC |
-+| MIPS | RTEMS | GCC |
-+| MIPS64 | Linux | GCC |
-+| Moxie | Bare metal | GCC |
-+| Nios II | Linux | GCC |
-+| OpenRISC | Linux | GCC |
-+| PowerPC 32-bit | AIX | IBM XL C |
-+| PowerPC 64-bit | AIX | IBM XL C |
-+| PowerPC | AMIGA | GCC |
-+| PowerPC | Linux | GCC |
-+| PowerPC | Mac OSX | GCC |
-+| PowerPC | FreeBSD | GCC |
-+| PowerPC 64-bit | FreeBSD | GCC |
-+| PowerPC 64-bit | Linux ELFv1 | GCC |
-+| PowerPC 64-bit | Linux ELFv2 | GCC |
-+| S390 | Linux | GCC |
-+| S390X | Linux | GCC |
-+| SPARC | Linux | GCC |
-+| SPARC | Solaris | GCC |
-+| SPARC | Solaris | Oracle Solaris Studio C |
-+| SPARC64 | Linux | GCC |
-+| SPARC64 | FreeBSD | GCC |
-+| SPARC64 | Solaris | Oracle Solaris Studio C |
-+| TILE-Gx/TILEPro | Linux | GCC |
-+| VAX | OpenBSD/vax | GCC |
-+| X86 | FreeBSD | GCC |
-+| X86 | GNU HURD | GCC |
-+| X86 | Interix | GCC |
-+| X86 | kFreeBSD | GCC |
-+| X86 | Linux | GCC |
-+| X86 | Mac OSX | GCC |
-+| X86 | OpenBSD | GCC |
-+| X86 | OS/2 | GCC |
-+| X86 | Solaris | GCC |
-+| X86 | Solaris | Oracle Solaris Studio C |
-+| X86 | Windows/Cygwin | GCC |
-+| X86 | Windows/MingW | GCC |
-+| X86-64 | FreeBSD | GCC |
-+| X86-64 | Linux | GCC |
-+| X86-64 | Linux/x32 | GCC |
-+| X86-64 | OpenBSD | GCC |
-+| X86-64 | Solaris | Oracle Solaris Studio C |
-+| X86-64 | Windows/Cygwin | GCC |
-+| X86-64 | Windows/MingW | GCC |
-+| Xtensa | Linux | GCC |
-+|-----------------+------------------+-------------------------|
++typedef enum {
++ FFI_OK = 0,
++ FFI_BAD_TYPEDEF,
++ FFI_BAD_ABI
++} ffi_status;
+
-+Please send additional platform test results to
-+libffi-discuss@sourceware.org and feel free to update the wiki page
-+above.
++typedef unsigned FFI_TYPE;
+
-+Installing libffi
-+=================
++typedef struct {
++ ffi_abi abi;
++ unsigned nargs;
++ ffi_type **arg_types;
++ ffi_type *rtype;
++ unsigned bytes;
++ unsigned flags;
++#ifdef FFI_EXTRA_CIF_FIELDS
++ FFI_EXTRA_CIF_FIELDS;
++#endif
++} ffi_cif;
+
-+First you must configure the distribution for your particular
-+system. Go to the directory you wish to build libffi in and run the
-+"configure" program found in the root directory of the libffi source
-+distribution.
++#if 0
++/* Used to adjust size/alignment of ffi types. */
++void ffi_prep_types (ffi_abi abi);
++#endif
+
-+If you're building libffi directly from version control, configure won't
-+exist yet; run ./autogen.sh first.
++/* Used internally, but overridden by some architectures */
++ffi_status ffi_prep_cif_core(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int isvariadic,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+You may want to tell configure where to install the libffi library and
-+header files. To do that, use the --prefix configure switch. Libffi
-+will install under /usr/local by default.
++/* ---- Definitions for the raw API -------------------------------------- */
+
-+If you want to enable extra run-time debugging checks use the the
-+--enable-debug configure switch. This is useful when your program dies
-+mysteriously while using libffi.
++#ifndef FFI_SIZEOF_ARG
++# if LONG_MAX == 2147483647
++# define FFI_SIZEOF_ARG 4
++# elif LONG_MAX == FFI_64_BIT_MAX
++# define FFI_SIZEOF_ARG 8
++# endif
++#endif
+
-+Another useful configure switch is --enable-purify-safety. Using this
-+will add some extra code which will suppress certain warnings when you
-+are using Purify with libffi. Only use this switch when using
-+Purify, as it will slow down the library.
++#ifndef FFI_SIZEOF_JAVA_RAW
++# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
++#endif
+
-+It's also possible to build libffi on Windows platforms with
-+Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
-+wrapper script during configuration like so:
++typedef union {
++ ffi_sarg sint;
++ ffi_arg uint;
++ float flt;
++ char data[FFI_SIZEOF_ARG];
++ void* ptr;
++} ffi_raw;
+
-+path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP"
++#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
++/* This is a special case for mips64/n32 ABI (and perhaps others) where
++ sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
++typedef union {
++ signed int sint;
++ unsigned int uint;
++ float flt;
++ char data[FFI_SIZEOF_JAVA_RAW];
++ void* ptr;
++} ffi_java_raw;
++#else
++typedef ffi_raw ffi_java_raw;
++#endif
+
-+For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64" and
-+CXX="path/to/msvcc.sh -m64". You may also need to specify --build
-+appropriately.
+
-+It is also possible to build libffi on Windows platforms with the LLVM
-+project's clang-cl compiler, like below:
++void ffi_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_raw *avalue);
+
-+path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
++void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
++void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
++size_t ffi_raw_size (ffi_cif *cif);
+
-+When building with MSVC under a MingW environment, you may need to
-+remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath'
-+command. ('cygpath' is not present in MingW, and is not required when
-+using MingW-style paths.)
++/* This is analogous to the raw API, except it uses Java parameter */
++/* packing, even on 64-bit machines. I.e. on 64-bit machines */
++/* longs and doubles are followed by an empty 64-bit word. */
+
-+For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
++void ffi_java_raw_call (ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ ffi_java_raw *avalue);
+
-+Configure has many other options. Use "configure --help" to see them all.
++void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
++void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
++size_t ffi_java_raw_size (ffi_cif *cif);
+
-+Once configure has finished, type "make". Note that you must be using
-+GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make .
++/* ---- Definitions for closures ----------------------------------------- */
+
-+To ensure that libffi is working as advertised, type "make check".
-+This will require that you have DejaGNU installed.
++#if FFI_CLOSURES
+
-+To install the library and header files, type "make install".
++#ifdef _MSC_VER
++__declspec(align(8))
++#endif
++typedef struct {
++#if 0
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++ void *user_data;
++#ifdef __GNUC__
++} ffi_closure __attribute__((aligned (8)));
++#else
++} ffi_closure;
++# ifdef __sgi
++# pragma pack 0
++# endif
++#endif
+
++void *ffi_closure_alloc (size_t size, void **code);
++void ffi_closure_free (void *);
+
-+History
-+=======
++ffi_status
++ffi_prep_closure (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data);
+
-+See the git log for details at http://github.com/atgreen/libffi.
++ffi_status
++ffi_prep_closure_loc (ffi_closure*,
++ ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*),
++ void *user_data,
++ void*codeloc);
+
-+4.0 TBD
-+ New API in support of GO closures.
++#ifdef __sgi
++# pragma pack 8
++#endif
++typedef struct {
++#if 0
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++ ffi_cif *cif;
+
-+3.2.1 Nov-12-14
-+ Build fix for non-iOS AArch64 targets.
++#if !FFI_NATIVE_RAW_API
+
-+3.2 Nov-11-14
-+ Add C99 Complex Type support (currently only supported on
-+ s390).
-+ Add support for PASCAL and REGISTER calling conventions on x86
-+ Windows/Linux.
-+ Add OpenRISC and Cygwin-64 support.
-+ Bug fixes.
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+3.1 May-19-14
-+ Add AArch64 (ARM64) iOS support.
-+ Add Nios II support.
-+ Add m88k and DEC VAX support.
-+ Add support for stdcall, thiscall, and fastcall on non-Windows
-+ 32-bit x86 targets such as Linux.
-+ Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi
-+ fixes.
-+ Make the testsuite more robust: eliminate several spurious
-+ failures, and respect the $CC and $CXX environment variables.
-+ Archive off the manually maintained ChangeLog in favor of git
-+ log.
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+3.0.13 Mar-17-13
-+ Add Meta support.
-+ Add missing Moxie bits.
-+ Fix stack alignment bug on 32-bit x86.
-+ Build fix for m68000 targets.
-+ Build fix for soft-float Power targets.
-+ Fix the install dir location for some platforms when building
-+ with GCC (OS X, Solaris).
-+ Fix Cygwin regression.
++#endif
+
-+3.0.12 Feb-11-13
-+ Add Moxie support.
-+ Add AArch64 support.
-+ Add Blackfin support.
-+ Add TILE-Gx/TILEPro support.
-+ Add MicroBlaze support.
-+ Add Xtensa support.
-+ Add support for PaX enabled kernels with MPROTECT.
-+ Add support for native vendor compilers on
-+ Solaris and AIX.
-+ Work around LLVM/GCC interoperability issue on x86_64.
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
++ void *user_data;
+
-+3.0.11 Apr-11-12
-+ Lots of build fixes.
-+ Add support for variadic functions (ffi_prep_cif_var).
-+ Add Linux/x32 support.
-+ Add thiscall, fastcall and MSVC cdecl support on Windows.
-+ Add Amiga and newer MacOS support.
-+ Add m68k FreeMiNT support.
-+ Integration with iOS' xcode build tools.
-+ Fix Octeon and MC68881 support.
-+ Fix code pessimizations.
++} ffi_raw_closure;
+
-+3.0.10 Aug-23-11
-+ Add support for Apple's iOS.
-+ Add support for ARM VFP ABI.
-+ Add RTEMS support for MIPS and M68K.
-+ Fix instruction cache clearing problems on
-+ ARM and SPARC.
-+ Fix the N64 build on mips-sgi-irix6.5.
-+ Enable builds with Microsoft's compiler.
-+ Enable x86 builds with Oracle's Solaris compiler.
-+ Fix support for calling code compiled with Oracle's Sparc
-+ Solaris compiler.
-+ Testsuite fixes for Tru64 Unix.
-+ Additional platform support.
++typedef struct {
++#if 0
++ void *trampoline_table;
++ void *trampoline_table_entry;
++#else
++ char tramp[FFI_TRAMPOLINE_SIZE];
++#endif
++
++ ffi_cif *cif;
++
++#if !FFI_NATIVE_RAW_API
++
++ /* if this is enabled, then a raw closure has the same layout
++ as a regular closure. We use this to install an intermediate
++ handler to do the transaltion, void** -> ffi_raw*. */
+
-+3.0.9 Dec-31-09
-+ Add AVR32 and win64 ports. Add ARM softfp support.
-+ Many fixes for AIX, Solaris, HP-UX, *BSD.
-+ Several PowerPC and x86-64 bug fixes.
-+ Build DLL for windows.
++ void (*translate_args)(ffi_cif*,void*,void**,void*);
++ void *this_closure;
+
-+3.0.8 Dec-19-08
-+ Add *BSD, BeOS, and PA-Linux support.
++#endif
+
-+3.0.7 Nov-11-08
-+ Fix for ppc FreeBSD.
-+ (thanks to Andreas Tobler)
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
++ void *user_data;
+
-+3.0.6 Jul-17-08
-+ Fix for closures on sh.
-+ Mark the sh/sh64 stack as non-executable.
-+ (both thanks to Kaz Kojima)
++} ffi_java_raw_closure;
+
-+3.0.5 Apr-3-08
-+ Fix libffi.pc file.
-+ Fix #define ARM for IcedTea users.
-+ Fix x86 closure bug.
++ffi_status
++ffi_prep_raw_closure (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data);
+
-+3.0.4 Feb-24-08
-+ Fix x86 OpenBSD configury.
++ffi_status
++ffi_prep_raw_closure_loc (ffi_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+3.0.3 Feb-22-08
-+ Enable x86 OpenBSD thanks to Thomas Heller, and
-+ x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
-+ Clean up test instruction in README.
++ffi_status
++ffi_prep_java_raw_closure (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data);
+
-+3.0.2 Feb-21-08
-+ Improved x86 FreeBSD support.
-+ Thanks to Björn König.
++ffi_status
++ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
++ ffi_cif *cif,
++ void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
++ void *user_data,
++ void *codeloc);
+
-+3.0.1 Feb-15-08
-+ Fix instruction cache flushing bug on MIPS.
-+ Thanks to David Daney.
++#endif /* FFI_CLOSURES */
+
-+3.0.0 Feb-15-08
-+ Many changes, mostly thanks to the GCC project.
-+ Cygnus Solutions is now Red Hat.
++#if FFI_GO_CLOSURES
+
-+ [10 years go by...]
++typedef struct {
++ void *tramp;
++ ffi_cif *cif;
++ void (*fun)(ffi_cif*,void*,void**,void*);
++} ffi_go_closure;
+
-+1.20 Oct-5-98
-+ Raffaele Sena produces ARM port.
++ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,
++ void (*fun)(ffi_cif*,void*,void**,void*));
+
-+1.19 Oct-5-98
-+ Fixed x86 long double and long long return support.
-+ m68k bug fixes from Andreas Schwab.
-+ Patch for DU assembler compatibility for the Alpha from Richard
-+ Henderson.
++void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
++ void **avalue, void *closure);
+
-+1.18 Apr-17-98
-+ Bug fixes and MIPS configuration changes.
++#endif /* FFI_GO_CLOSURES */
+
-+1.17 Feb-24-98
-+ Bug fixes and m68k port from Andreas Schwab. PowerPC port from
-+ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
++/* ---- Public interface definition -------------------------------------- */
+
-+1.16 Feb-11-98
-+ Richard Henderson produces Alpha port.
++ffi_status ffi_prep_cif(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+1.15 Dec-4-97
-+ Fixed an n32 ABI bug. New libtool, auto* support.
++ffi_status ffi_prep_cif_var(ffi_cif *cif,
++ ffi_abi abi,
++ unsigned int nfixedargs,
++ unsigned int ntotalargs,
++ ffi_type *rtype,
++ ffi_type **atypes);
+
-+1.14 May-13-97
-+ libtool is now used to generate shared and static libraries.
-+ Fixed a minor portability problem reported by Russ McManus
-+ .
++void ffi_call(ffi_cif *cif,
++ void (*fn)(void),
++ void *rvalue,
++ void **avalue);
+
-+1.13 Dec-2-96
-+ Added --enable-purify-safety to keep Purify from complaining
-+ about certain low level code.
-+ Sparc fix for calling functions with < 6 args.
-+ Linux x86 a.out fix.
++/* Useful for eliminating compiler warnings */
++#define FFI_FN(f) ((void (*)(void))f)
+
-+1.12 Nov-22-96
-+ Added missing ffi_type_void, needed for supporting void return
-+ types. Fixed test case for non MIPS machines. Cygnus Support
-+ is now Cygnus Solutions.
++/* ---- Definitions shared with assembly code ---------------------------- */
+
-+1.11 Oct-30-96
-+ Added notes about GNU make.
++#endif
+
-+1.10 Oct-29-96
-+ Added configuration fix for non GNU compilers.
++/* If these change, update src/mips/ffitarget.h. */
++#define FFI_TYPE_VOID 0
++#define FFI_TYPE_INT 1
++#define FFI_TYPE_FLOAT 2
++#define FFI_TYPE_DOUBLE 3
++#if 1
++#define FFI_TYPE_LONGDOUBLE 4
++#else
++#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
++#endif
++#define FFI_TYPE_UINT8 5
++#define FFI_TYPE_SINT8 6
++#define FFI_TYPE_UINT16 7
++#define FFI_TYPE_SINT16 8
++#define FFI_TYPE_UINT32 9
++#define FFI_TYPE_SINT32 10
++#define FFI_TYPE_UINT64 11
++#define FFI_TYPE_SINT64 12
++#define FFI_TYPE_STRUCT 13
++#define FFI_TYPE_POINTER 14
++#define FFI_TYPE_COMPLEX 15
+
-+1.09 Oct-29-96
-+ Added --enable-debug configure switch. Clean-ups based on LCLint
-+ feedback. ffi_mips.h is always installed. Many configuration
-+ fixes. Fixed ffitest.c for sparc builds.
++/* This should always refer to the last type code (for sanity checks) */
++#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
+
-+1.08 Oct-15-96
-+ Fixed n32 problem. Many clean-ups.
++#ifdef __cplusplus
++}
++#endif
+
-+1.07 Oct-14-96
-+ Gordon Irlam rewrites v8.S again. Bug fixes.
++#endif
+
-+1.06 Oct-14-96
-+ Gordon Irlam improved the sparc port.
+
-+1.05 Oct-14-96
-+ Interface changes based on feedback.
++#endif
+\ No newline at end of file
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig.h modified/Modules/_ctypes/libffi_ios/include/fficonfig.h
+--- orig/Modules/_ctypes/libffi_ios/include/fficonfig.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/fficonfig.h 2015-12-20 18:55:19.000000000 +0800
+@@ -0,0 +1,24 @@
++#ifdef __arm64__
+
-+1.04 Oct-11-96
-+ Sparc port complete (modulo struct passing bug).
++#include
+
-+1.03 Oct-10-96
-+ Passing struct args, and returning struct values works for
-+ all architectures/calling conventions. Expanded tests.
+
-+1.02 Oct-9-96
-+ Added SGI n32 support. Fixed bugs in both o32 and Linux support.
-+ Added "make test".
++#endif
++#ifdef __i386__
+
-+1.01 Oct-8-96
-+ Fixed float passing bug in mips version. Restructured some
-+ of the code. Builds cleanly with SGI tools.
++#include
+
-+1.00 Oct-7-96
-+ First release. No public announcement.
+
++#endif
++#ifdef __arm__
+
-+Authors & Credits
-+=================
++#include
+
-+libffi was originally written by Anthony Green .
+
-+The developers of the GNU Compiler Collection project have made
-+innumerable valuable contributions. See the ChangeLog file for
-+details.
++#endif
++#ifdef __x86_64__
+
-+Some of the ideas behind libffi were inspired by Gianni Mariani's free
-+gencall library for Silicon Graphics machines.
++#include
+
-+The closure mechanism was designed and implemented by Kresten Krab
-+Thorup.
+
-+Major processor architecture ports were contributed by the following
-+developers:
++#endif
+diff -Nru orig/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h modified/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h
+--- orig/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h 1970-01-01 08:00:00.000000000 +0800
++++ modified/Modules/_ctypes/libffi_ios/include/fficonfig_arm64.h 2015-12-20 18:55:29.000000000 +0800
+@@ -0,0 +1,214 @@
++#ifdef __arm64__
+
-+aarch64 Marcus Shawcroft, James Greenhalgh
-+alpha Richard Henderson
-+arm Raffaele Sena
-+blackfin Alexandre Keunecke I. de Mendonca
-+cris Simon Posnjak, Hans-Peter Nilsson
-+frv Anthony Green
-+ia64 Hans Boehm
-+m32r Kazuhiro Inaoka
-+m68k Andreas Schwab
-+m88k Miod Vallat
-+microblaze Nathan Rossi
-+mips Anthony Green, Casey Marshall
-+mips64 David Daney
-+moxie Anthony Green
-+nios ii Sandra Loosemore
-+openrisc Sebastian Macke
-+pa Randolph Chung, Dave Anglin, Andreas Tobler
-+powerpc Geoffrey Keating, Andreas Tobler,
-+ David Edelsohn, John Hornkvist
-+powerpc64 Jakub Jelinek
-+s390 Gerhard Tonn, Ulrich Weigand
-+sh Kaz Kojima
-+sh64 Kaz Kojima
-+sparc Anthony Green, Gordon Irlam
-+tile-gx/tilepro Walter Lee
-+vax Miod Vallat
-+x86 Anthony Green, Jon Beniston
-+x86-64 Bo Thorsen
-+xtensa Chris Zankel
++/* fficonfig.h. Generated from fficonfig.h.in by configure. */
++/* fficonfig.h.in. Generated from configure.ac by autoheader. */
++
++/* Define if building universal (internal helper macro) */
++/* #undef AC_APPLE_UNIVERSAL_BUILD */
++
++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
++ systems. This function is required for `alloca.c' support on those systems.
++ */
++/* #undef CRAY_STACKSEG_END */
++
++/* Define to 1 if using `alloca.c'. */
++/* #undef C_ALLOCA */
++
++/* Define to the flags needed for the .section .eh_frame directive. */
++#define EH_FRAME_FLAGS "aw"
+
-+Jesper Skov and Andrew Haley both did more than their fair share of
-+stepping through the code and tracking down bugs.
++/* Define this if you want extra debugging. */
++/* #undef FFI_DEBUG */
+
-+Thanks also to Tom Tromey for bug fixes, documentation and
-+configuration help.
++/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
++#define FFI_EXEC_TRAMPOLINE_TABLE 1
+
-+Thanks to Jim Blandy, who provided some useful feedback on the libffi
-+interface.
++/* Define this if you want to enable pax emulated trampolines */
++/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */
+
-+Andreas Tobler has done a tremendous amount of work on the testsuite.
++/* Cannot use malloc on this target, so, we revert to alternative means */
++/* #undef FFI_MMAP_EXEC_WRIT */
+
-+Alex Oliva solved the executable page problem for SElinux.
++/* Define this if you do not want support for the raw API. */
++/* #undef FFI_NO_RAW_API */
+
-+The list above is almost certainly incomplete and inaccurate. I'm
-+happy to make corrections or additions upon request.
++/* Define this if you do not want support for aggregate types. */
++/* #undef FFI_NO_STRUCTS */
+
-+If you have a problem, or have found a bug, please send a note to the
-+author at green@moxielogic.com, or the project mailing list at
-+libffi-discuss@sourceware.org.
-diff -Nru orig/Modules/_ctypes/libffi_ios_aarch64/README.python modified/Modules/_ctypes/libffi_ios_aarch64/README.python
---- orig/Modules/_ctypes/libffi_ios_aarch64/README.python 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios_aarch64/README.python 2015-04-26 08:58:26.000000000 +0800
-@@ -0,0 +1,17 @@
-+This directory contains the generated source code for running libffi
-+on iOS platforms (physical and simulator). It contains support for
-+ARM64 (referred to as `aarch64` by libffi).
++/* Define to 1 if you have `alloca', as a function or macro. */
++#define HAVE_ALLOCA 1
+
-+libffi requires a code-generation step for Apple platforms. This code
-+generation is performed using the `generate-darwin-source-and-headers.py`
-+script in the home directory of the libffi project.
++/* Define to 1 if you have and it should be used (not on Ultrix).
++ */
++#define HAVE_ALLOCA_H 1
+
-+This directory is the combined output of the darwin_common and darwin_ios
-+generated code directories. It has been pruned of source files that are
-+not needed for ctypes.
++/* Define if your assembler supports .cfi_* directives. */
++#define HAVE_AS_CFI_PSEUDO_OP 1
+
-+The code in this directory comes from a pre-release version of libffi 4.0.
-+March 29 2015, Git hash 17ffc3655a531c116e9eb9cc933e50bb1e5c47f8.
++/* Define if your assembler supports .register. */
++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
+
-+The pre-release version is necessary because the stable 3.2.1 release
-+contains bugs on the ARM64 platform.
-diff -Nru orig/Modules/_ctypes/libffi_ios_aarch64/aarch64/ffi_arm64.c modified/Modules/_ctypes/libffi_ios_aarch64/aarch64/ffi_arm64.c
---- orig/Modules/_ctypes/libffi_ios_aarch64/aarch64/ffi_arm64.c 1970-01-01 08:00:00.000000000 +0800
-+++ modified/Modules/_ctypes/libffi_ios_aarch64/aarch64/ffi_arm64.c 2015-04-26 08:39:44.000000000 +0800
-@@ -0,0 +1,1157 @@
-+#ifdef __arm64__
++/* Define if the compiler uses zarch features. */
++/* #undef HAVE_AS_S390_ZARCH */
+
-+/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
++/* Define if your assembler and linker support unaligned PC relative relocs.
++ */
++/* #undef HAVE_AS_SPARC_UA_PCREL */
+
-+Permission is hereby granted, free of charge, to any person obtaining
-+a copy of this software and associated documentation files (the
-+``Software''), to deal in the Software without restriction, including
-+without limitation the rights to use, copy, modify, merge, publish,
-+distribute, sublicense, and/or sell copies of the Software, and to
-+permit persons to whom the Software is furnished to do so, subject to
-+the following conditions:
++/* Define if your assembler supports unwind section type. */
++/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
+
-+The above copyright notice and this permission notice shall be
-+included in all copies or substantial portions of the Software.
++/* Define if your assembler supports PC relative relocs. */
++/* #undef HAVE_AS_X86_PCREL */
+
-+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
-+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
++/* Define to 1 if you have the header file. */
++#define HAVE_DLFCN_H 1
+
-+#include
-+#include