diff --git a/libobjc.order b/libobjc.order
index c7415fc..1d56c59 100644
--- a/libobjc.order
+++ b/libobjc.order
@@ -19,8 +19,6 @@ __objc_update_stubs_in_mach_header
_sel_init
___sel_registerName
__objc_search_builtins
-__ZNK8objc_opt13objc_selopt_t3getEPKc
-__ZNK8objc_opt13objc_selopt_t4hashEPKc
_sel_registerName
_arr_init
__ZN4objc8DenseMapIP11objc_objectmLb1ENS_12DenseMapInfoIS2_EENS3_ImEEE4initEj
diff --git a/markgc.cpp b/markgc.cpp
index 4543ad6..bed92dd 100644
--- a/markgc.cpp
+++ b/markgc.cpp
@@ -391,6 +391,14 @@ void dosect(uint8_t *start, macho_section
*sect)
sect->set_sectname("__objc_init_func");
if (debug) printf("disabled __mod_init_func section\n");
}
+ if (segnameStartsWith(sect->segname(), "__TEXT") &&
+ sectnameEquals(sect->sectname(), "__init_offsets"))
+ {
+ // section type 0 is S_REGULAR
+ sect->set_flags(sect->flags() & ~SECTION_TYPE);
+ sect->set_sectname("__objc_init_offs");
+ if (debug) printf("disabled __mod_init_func section\n");
+ }
if (segnameStartsWith(sect->segname(), "__DATA") &&
sectnameEquals(sect->sectname(), "__mod_term_func"))
{
diff --git a/objc.sln b/objc.sln
old mode 100644
new mode 100755
diff --git a/objc.xcodeproj/project.pbxproj b/objc.xcodeproj/project.pbxproj
index 80c47fb..9f3248f 100644
--- a/objc.xcodeproj/project.pbxproj
+++ b/objc.xcodeproj/project.pbxproj
@@ -7,6 +7,17 @@
objects = {
/* Begin PBXAggregateTarget section */
+ 6EF877EF23263D7000963DBB /* objc_executables */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 6EF877F223263D7000963DBB /* Build configuration list for PBXAggregateTarget "objc_executables" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 6EF877F423263D8000963DBB /* PBXTargetDependency */,
+ );
+ name = objc_executables;
+ productName = "objc-executables";
+ };
834F9B01212E560100F95A54 /* objc4_tests */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 834F9B04212E560200F95A54 /* Build configuration list for PBXAggregateTarget "objc4_tests" */;
@@ -45,6 +56,13 @@
6EACB842232C97A400CE9176 /* objc-zalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EACB841232C97A400CE9176 /* objc-zalloc.h */; };
6EACB844232C97B900CE9176 /* objc-zalloc.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6EACB843232C97B900CE9176 /* objc-zalloc.mm */; };
6ECD0B1F2244999E00910D88 /* llvm-DenseSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ECD0B1E2244999E00910D88 /* llvm-DenseSet.h */; };
+ 6EF877DA2325D62600963DBB /* objcdt.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6EF877D92325D62600963DBB /* objcdt.mm */; };
+ 6EF877DE2325D79000963DBB /* objc-probes.d in Sources */ = {isa = PBXBuildFile; fileRef = 87BB4E900EC39633005D08E1 /* objc-probes.d */; };
+ 6EF877E02325D92E00963DBB /* CoreSymbolication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6EF877DF2325D92E00963DBB /* CoreSymbolication.framework */; };
+ 6EF877E22325D93200963DBB /* Symbolication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6EF877E12325D93200963DBB /* Symbolication.framework */; };
+ 6EF877E52325FAC400963DBB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6EF877E42325FAC400963DBB /* Foundation.framework */; };
+ 6EF877E82326184000963DBB /* json.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6EF877E72326184000963DBB /* json.mm */; };
+ 6EF877EC232635A700963DBB /* objcdt.1 in Install Manpages */ = {isa = PBXBuildFile; fileRef = 6EF877EA232633CC00963DBB /* objcdt.1 */; };
7213C36321FA7C730090A271 /* NSObject-internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7213C36221FA7C730090A271 /* NSObject-internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
7593EC58202248E50046AB96 /* objc-object.h in Headers */ = {isa = PBXBuildFile; fileRef = 7593EC57202248DF0046AB96 /* objc-object.h */; };
75A9504F202BAA0600D7D56F /* objc-locks-new.h in Headers */ = {isa = PBXBuildFile; fileRef = 75A9504E202BAA0300D7D56F /* objc-locks-new.h */; };
@@ -128,12 +146,22 @@
83F550E0155E030800E95D3B /* objc-cache-old.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83F550DF155E030800E95D3B /* objc-cache-old.mm */; };
87BB4EA70EC39854005D08E1 /* objc-probes.d in Sources */ = {isa = PBXBuildFile; fileRef = 87BB4E900EC39633005D08E1 /* objc-probes.d */; };
9672F7EE14D5F488007CEC96 /* NSObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9672F7ED14D5F488007CEC96 /* NSObject.mm */; };
+ C22F5208230EF38B001BFE14 /* objc-ptrauth.h in Headers */ = {isa = PBXBuildFile; fileRef = C22F5207230EF38B001BFE14 /* objc-ptrauth.h */; };
C2E6D3FC2225DCF00059DFAA /* DenseMapExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E6D3FB2225DCF00059DFAA /* DenseMapExtras.h */; };
+ C2EB731D23D8A38A0040672B /* dummy-library-mac-i386.c in Sources */ = {isa = PBXBuildFile; fileRef = C2EB731C23D8A38A0040672B /* dummy-library-mac-i386.c */; };
E8923DA5116AB2820071B552 /* objc-block-trampolines.mm in Sources */ = {isa = PBXBuildFile; fileRef = E8923DA0116AB2820071B552 /* objc-block-trampolines.mm */; };
+ E934A9F123E996D00088F26F /* objc4.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = E934A9EF23E9967D0088F26F /* objc4.plist */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
F9BCC71B205C68E800DD9AFC /* objc-blocktramps-arm64.s in Sources */ = {isa = PBXBuildFile; fileRef = 8379996D13CBAF6F007C2B5F /* objc-blocktramps-arm64.s */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 6EF877F323263D8000963DBB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 6EF877D62325D62600963DBB;
+ remoteInfo = objcdt;
+ };
837F67AC1A771F6E004D34FA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -150,6 +178,30 @@
};
/* End PBXContainerItemProxy section */
+/* Begin PBXCopyFilesBuildPhase section */
+ 6EF877D52325D62600963DBB /* Install Manpages */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/local/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 6EF877EC232635A700963DBB /* objcdt.1 in Install Manpages */,
+ );
+ name = "Install Manpages";
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ E934A9F023E996CC0088F26F /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /System/Library/FeatureFlags/Domain;
+ dstSubfolderSpec = 0;
+ files = (
+ E934A9F123E996D00088F26F /* objc4.plist in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
/* Begin PBXFileReference section */
393CEABF0DC69E3E000B69DE /* objc-references.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "objc-references.mm"; path = "runtime/objc-references.mm"; sourceTree = ""; };
393CEAC50DC69E67000B69DE /* objc-references.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "objc-references.h"; path = "runtime/objc-references.h"; sourceTree = ""; };
@@ -164,6 +216,15 @@
6EACB841232C97A400CE9176 /* objc-zalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "objc-zalloc.h"; path = "runtime/objc-zalloc.h"; sourceTree = ""; };
6EACB843232C97B900CE9176 /* objc-zalloc.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "objc-zalloc.mm"; path = "runtime/objc-zalloc.mm"; sourceTree = ""; };
6ECD0B1E2244999E00910D88 /* llvm-DenseSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "llvm-DenseSet.h"; path = "runtime/llvm-DenseSet.h"; sourceTree = ""; };
+ 6EF877D72325D62600963DBB /* objcdt */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = objcdt; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6EF877D92325D62600963DBB /* objcdt.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = objcdt.mm; sourceTree = ""; usesTabs = 0; };
+ 6EF877DF2325D92E00963DBB /* CoreSymbolication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSymbolication.framework; path = System/Library/PrivateFrameworks/CoreSymbolication.framework; sourceTree = SDKROOT; };
+ 6EF877E12325D93200963DBB /* Symbolication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Symbolication.framework; path = System/Library/PrivateFrameworks/Symbolication.framework; sourceTree = SDKROOT; };
+ 6EF877E32325D95300963DBB /* objcdt-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "objcdt-entitlements.plist"; sourceTree = ""; };
+ 6EF877E42325FAC400963DBB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 6EF877E62326184000963DBB /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = ""; usesTabs = 1; };
+ 6EF877E72326184000963DBB /* json.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = json.mm; sourceTree = ""; usesTabs = 1; };
+ 6EF877EA232633CC00963DBB /* objcdt.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = objcdt.1; sourceTree = ""; };
7213C36221FA7C730090A271 /* NSObject-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSObject-internal.h"; path = "runtime/NSObject-internal.h"; sourceTree = ""; };
7593EC57202248DF0046AB96 /* objc-object.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "objc-object.h"; path = "runtime/objc-object.h"; sourceTree = ""; };
75A9504E202BAA0300D7D56F /* objc-locks-new.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "objc-locks-new.h"; path = "runtime/objc-locks-new.h"; sourceTree = ""; };
@@ -252,15 +313,32 @@
87BB4E900EC39633005D08E1 /* objc-probes.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "objc-probes.d"; path = "runtime/objc-probes.d"; sourceTree = ""; };
9672F7ED14D5F488007CEC96 /* NSObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NSObject.mm; path = runtime/NSObject.mm; sourceTree = ""; };
BC8B5D1212D3D48100C78A5B /* libauto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libauto.dylib; path = /usr/lib/libauto.dylib; sourceTree = ""; };
+ C217B55222DE556D004369BA /* objc-env.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "objc-env.h"; path = "runtime/objc-env.h"; sourceTree = ""; };
+ C2296C682457336C003FAE61 /* objc-bp-assist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "objc-bp-assist.h"; path = "runtime/objc-bp-assist.h"; sourceTree = ""; };
+ C22F5207230EF38B001BFE14 /* objc-ptrauth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "objc-ptrauth.h"; path = "runtime/objc-ptrauth.h"; sourceTree = ""; };
C2E6D3FB2225DCF00059DFAA /* DenseMapExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DenseMapExtras.h; path = runtime/DenseMapExtras.h; sourceTree = ""; };
+ C2EB731C23D8A38A0040672B /* dummy-library-mac-i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "dummy-library-mac-i386.c"; path = "runtime/dummy-library-mac-i386.c"; sourceTree = ""; };
D2AAC0630554660B00DB518D /* libobjc.A.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libobjc.A.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
E8923D9C116AB2820071B552 /* objc-blocktramps-i386.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = "objc-blocktramps-i386.s"; path = "runtime/objc-blocktramps-i386.s"; sourceTree = ""; };
E8923D9D116AB2820071B552 /* objc-blocktramps-x86_64.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = "objc-blocktramps-x86_64.s"; path = "runtime/objc-blocktramps-x86_64.s"; sourceTree = ""; };
E8923DA0116AB2820071B552 /* objc-block-trampolines.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "objc-block-trampolines.mm"; path = "runtime/objc-block-trampolines.mm"; sourceTree = ""; };
+ E934A9EF23E9967D0088F26F /* objc4.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = objc4.plist; sourceTree = ""; };
+ E97047552497CC5300781D29 /* check_preopt_caches.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = check_preopt_caches.entitlements; sourceTree = ""; };
+ E9AD465924925261002AF1DB /* check_preopt_caches.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = check_preopt_caches.mm; sourceTree = ""; };
F9BCC727205C68E800DD9AFC /* libobjc-trampolines.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "libobjc-trampolines.dylib"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 6EF877D42325D62600963DBB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6EF877E22325D93200963DBB /* Symbolication.framework in Frameworks */,
+ 6EF877E52325FAC400963DBB /* Foundation.framework in Frameworks */,
+ 6EF877E02325D92E00963DBB /* CoreSymbolication.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D289988505E68E00004EDB86 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -289,6 +367,8 @@
838486270D6D690F00CEA253 /* Obsolete Source */,
08FB7795FE84155DC02AAC07 /* Source */,
838485B20D6D67F900CEA253 /* Other */,
+ 6EF877D82325D62600963DBB /* objcdt */,
+ E9AD465824925261002AF1DB /* check-preopt-caches */,
1AB674ADFE9D54B511CA2CBB /* Products */,
F9BCC72A205C6A1600DD9AFC /* Frameworks */,
);
@@ -298,6 +378,7 @@
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
+ C2EB731C23D8A38A0040672B /* dummy-library-mac-i386.c */,
838485B80D6D687300CEA253 /* hashtable2.mm */,
838485BC0D6D687300CEA253 /* maptable.mm */,
9672F7ED14D5F488007CEC96 /* NSObject.mm */,
@@ -352,10 +433,23 @@
children = (
D2AAC0630554660B00DB518D /* libobjc.A.dylib */,
F9BCC727205C68E800DD9AFC /* libobjc-trampolines.dylib */,
+ 6EF877D72325D62600963DBB /* objcdt */,
);
name = Products;
sourceTree = "";
};
+ 6EF877D82325D62600963DBB /* objcdt */ = {
+ isa = PBXGroup;
+ children = (
+ 6EF877EA232633CC00963DBB /* objcdt.1 */,
+ 6EF877E62326184000963DBB /* json.h */,
+ 6EF877E72326184000963DBB /* json.mm */,
+ 6EF877D92325D62600963DBB /* objcdt.mm */,
+ 6EF877E32325D95300963DBB /* objcdt-entitlements.plist */,
+ );
+ path = objcdt;
+ sourceTree = "";
+ };
838485B20D6D67F900CEA253 /* Other */ = {
isa = PBXGroup;
children = (
@@ -363,6 +457,7 @@
838485B40D6D683300CEA253 /* APPLE_LICENSE */,
838485B50D6D683300CEA253 /* ReleaseNotes.rtf */,
83CE671D1E6E76B60095A33E /* interposable.txt */,
+ E934A9EF23E9967D0088F26F /* objc4.plist */,
838485B30D6D682B00CEA253 /* libobjc.order */,
);
name = Other;
@@ -389,12 +484,13 @@
838485C70D6D688200CEA253 /* Private Headers */ = {
isa = PBXGroup;
children = (
- 7213C36221FA7C730090A271 /* NSObject-internal.h */,
- 83112ED30F00599600A5FBAF /* objc-internal.h */,
- 834EC0A311614167009B2563 /* objc-abi.h */,
838485BB0D6D687300CEA253 /* maptable.h */,
- 834266D70E665A8B002E4DA2 /* objc-gdb.h */,
+ 7213C36221FA7C730090A271 /* NSObject-internal.h */,
+ 834EC0A311614167009B2563 /* objc-abi.h */,
8306440620D24A3E00E356D2 /* objc-block-trampolines.h */,
+ 834266D70E665A8B002E4DA2 /* objc-gdb.h */,
+ 83112ED30F00599600A5FBAF /* objc-internal.h */,
+ C22F5207230EF38B001BFE14 /* objc-ptrauth.h */,
);
name = "Private Headers";
sourceTree = "";
@@ -437,6 +533,8 @@
83D9269721225A7400299F69 /* arm64-asm.h */,
83D92695212254CF00299F69 /* isa.h */,
838485CF0D6D68A200CEA253 /* objc-config.h */,
+ C2296C682457336C003FAE61 /* objc-bp-assist.h */,
+ C217B55222DE556D004369BA /* objc-env.h */,
83BE02E50FCCB24D00661494 /* objc-file-old.h */,
83BE02E60FCCB24D00661494 /* objc-file.h */,
838485D40D6D68A200CEA253 /* objc-initialize.h */,
@@ -457,9 +555,21 @@
name = "Project Headers";
sourceTree = "";
};
+ E9AD465824925261002AF1DB /* check-preopt-caches */ = {
+ isa = PBXGroup;
+ children = (
+ E97047552497CC5300781D29 /* check_preopt_caches.entitlements */,
+ E9AD465924925261002AF1DB /* check_preopt_caches.mm */,
+ );
+ path = "check-preopt-caches";
+ sourceTree = "";
+ };
F9BCC72A205C6A1600DD9AFC /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 6EF877E42325FAC400963DBB /* Foundation.framework */,
+ 6EF877E12325D93200963DBB /* Symbolication.framework */,
+ 6EF877DF2325D92E00963DBB /* CoreSymbolication.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -528,6 +638,7 @@
838486200D6D68A800CEA253 /* runtime.h in Headers */,
39ABD72312F0B61800D1054C /* objc-weak.h in Headers */,
83F4B52815E843B100E0926F /* NSObjCRuntime.h in Headers */,
+ C22F5208230EF38B001BFE14 /* objc-ptrauth.h in Headers */,
6ECD0B1F2244999E00910D88 /* llvm-DenseSet.h in Headers */,
83F4B52915E843B100E0926F /* NSObject.h in Headers */,
);
@@ -536,6 +647,23 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
+ 6EF877D62325D62600963DBB /* objcdt */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 6EF877DD2325D62600963DBB /* Build configuration list for PBXNativeTarget "objcdt" */;
+ buildPhases = (
+ 6EF877D32325D62600963DBB /* Sources */,
+ 6EF877D42325D62600963DBB /* Frameworks */,
+ 6EF877D52325D62600963DBB /* Install Manpages */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = objcdt;
+ productName = objcdt;
+ productReference = 6EF877D72325D62600963DBB /* objcdt */;
+ productType = "com.apple.product-type.tool";
+ };
D2AAC0620554660B00DB518D /* objc */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "objc" */;
@@ -545,6 +673,7 @@
D289988505E68E00004EDB86 /* Frameworks */,
830F2AB60D739AB600392440 /* Run Script (markgc) */,
830F2AFA0D73BC5800392440 /* Run Script (symlink) */,
+ E934A9F023E996CC0088F26F /* CopyFiles */,
);
buildRules = (
);
@@ -579,9 +708,15 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
- BuildIndependentTargetsInParallel = NO;
LastUpgradeCheck = 0440;
TargetAttributes = {
+ 6EF877D62325D62600963DBB = {
+ CreatedOnToolsVersion = 11.0;
+ };
+ 6EF877EF23263D7000963DBB = {
+ CreatedOnToolsVersion = 11.0;
+ ProvisioningStyle = Automatic;
+ };
834F9B01212E560100F95A54 = {
CreatedOnToolsVersion = 10.0;
DevelopmentTeam = 59GAB85EFG;
@@ -610,6 +745,8 @@
837F67A81A771F63004D34FA /* objc-simulator */,
F9BCC6CA205C68E800DD9AFC /* objc-trampolines */,
834F9B01212E560100F95A54 /* objc4_tests */,
+ 6EF877EF23263D7000963DBB /* objc_executables */,
+ 6EF877D62325D62600963DBB /* objcdt */,
);
};
/* End PBXProject section */
@@ -665,6 +802,16 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 6EF877D32325D62600963DBB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6EF877E82326184000963DBB /* json.mm in Sources */,
+ 6EF877DA2325D62600963DBB /* objcdt.mm in Sources */,
+ 6EF877DE2325D79000963DBB /* objc-probes.d in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
D2AAC0610554660B00DB518D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -705,6 +852,7 @@
83B1A8BE0FF1AC0D0019EA5B /* objc-msg-simulator-i386.s in Sources */,
83EB007B121C9EC200B92C16 /* objc-sel-table.s in Sources */,
39ABD72412F0B61800D1054C /* objc-weak.mm in Sources */,
+ C2EB731D23D8A38A0040672B /* dummy-library-mac-i386.c in Sources */,
83D49E4F13C7C84F0057F1DD /* objc-msg-arm64.s in Sources */,
9672F7EE14D5F488007CEC96 /* NSObject.mm in Sources */,
83725F4A14CA5BFA0014370E /* objc-opt.mm in Sources */,
@@ -729,6 +877,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
+ 6EF877F423263D8000963DBB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 6EF877D62325D62600963DBB /* objcdt */;
+ targetProxy = 6EF877F323263D8000963DBB /* PBXContainerItemProxy */;
+ };
837F67AD1A771F6E004D34FA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D2AAC0620554660B00DB518D /* objc */;
@@ -751,6 +904,8 @@
COPY_PHASE_STRIP = NO;
DEPLOYMENT_LOCATION = YES;
DYLIB_CURRENT_VERSION = 228;
+ EXCLUDED_SOURCE_FILE_NAMES = "dummy-library-mac-i386.c";
+ "EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*][arch=i386]" = "*";
EXECUTABLE_PREFIX = lib;
GCC_CW_ASM_SYNTAX = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -762,6 +917,7 @@
"$(CONFIGURATION_BUILD_DIR)/usr/local/include/**",
/System/Library/Frameworks/System.framework/PrivateHeaders,
);
+ "INCLUDED_SOURCE_FILE_NAMES[sdk=macosx*][arch=i386]" = "dummy-library-mac-i386.c";
INSTALL_PATH = /usr/lib;
IS_ZIPPERED = YES;
LLVM_LTO = NO;
@@ -787,6 +943,10 @@
"-interposable_list",
"-Xlinker",
interposable.txt,
+ "-Xlinker",
+ "-headerpad",
+ "-Xlinker",
+ 0x100,
);
"OTHER_LDFLAGS[sdk=iphonesimulator*][arch=*]" = (
"-lc++abi",
@@ -810,7 +970,9 @@
"-interposable_list",
"-Xlinker",
interposable.txt,
+ "-loah",
);
+ "OTHER_LDFLAGS[sdk=macosx*][arch=i386]" = "-nodefaultlibs";
OTHER_TAPI_FLAGS = "-exclude-public-header $(DSTROOT)/usr/include/objc/ObjectiveC.apinotes -exclude-public-header $(DSTROOT)/usr/include/objc/module.modulemap -Xparser -Wno-deprecated-declarations -Xparser -Wno-unavailable-declarations -Xparser -D_OBJC_PRIVATE_H_=1 -DOBJC_DECLARE_SYMBOLS=1";
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/objc;
PRODUCT_NAME = objc.A;
@@ -829,6 +991,8 @@
"COPY_HEADERS_UNIFDEF_FLAGS[sdk=macosx*]" = "-DBUILD_FOR_OSX";
DEPLOYMENT_LOCATION = YES;
DYLIB_CURRENT_VERSION = 228;
+ EXCLUDED_SOURCE_FILE_NAMES = "dummy-library-mac-i386.c";
+ "EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*][arch=i386]" = "*";
EXECUTABLE_PREFIX = lib;
GCC_CW_ASM_SYNTAX = NO;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
@@ -839,6 +1003,7 @@
"$(CONFIGURATION_BUILD_DIR)/usr/local/include/**",
/System/Library/Frameworks/System.framework/PrivateHeaders,
);
+ "INCLUDED_SOURCE_FILE_NAMES[sdk=macosx*][arch=i386]" = "dummy-library-mac-i386.c";
INSTALL_PATH = /usr/lib;
IS_ZIPPERED = YES;
ORDER_FILE = "$(SDKROOT)/AppleInternal/OrderFiles/libobjc.order";
@@ -863,6 +1028,10 @@
"-interposable_list",
"-Xlinker",
interposable.txt,
+ "-Xlinker",
+ "-headerpad",
+ "-Xlinker",
+ 0x100,
);
"OTHER_LDFLAGS[sdk=iphonesimulator*][arch=*]" = (
"-lc++abi",
@@ -886,7 +1055,9 @@
"-interposable_list",
"-Xlinker",
interposable.txt,
+ "-loah",
);
+ "OTHER_LDFLAGS[sdk=macosx*][arch=i386]" = "-nodefaultlibs";
OTHER_TAPI_FLAGS = "-exclude-public-header $(DSTROOT)/usr/include/objc/ObjectiveC.apinotes -exclude-public-header $(DSTROOT)/usr/include/objc/module.modulemap -Xparser -Wno-deprecated-declarations -Xparser -Wno-unavailable-declarations -Xparser -D_OBJC_PRIVATE_H_=1 -DOBJC_DECLARE_SYMBOLS=1";
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/objc;
PRODUCT_NAME = objc.A;
@@ -908,6 +1079,7 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
CLANG_OBJC_RUNTIME = NO;
+ CODE_SIGN_IDENTITY = "-";
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
@@ -954,6 +1126,7 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_LINK_OBJC_RUNTIME = NO;
CLANG_OBJC_RUNTIME = NO;
+ CODE_SIGN_IDENTITY = "-";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
@@ -995,6 +1168,59 @@
};
name = Release;
};
+ 6EF877DB2325D62600963DBB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = "objcdt/objcdt-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__BUILDING_OBJCDT__=1",
+ "$(inherited)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(SRCROOT)/runtime",
+ /System/Library/Frameworks/System.framework/PrivateHeaders,
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ };
+ name = Debug;
+ };
+ 6EF877DC2325D62600963DBB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = "objcdt/objcdt-entitlements.plist";
+ CODE_SIGN_IDENTITY = "-";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "__BUILDING_OBJCDT__=1",
+ "$(inherited)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(SRCROOT)/runtime",
+ /System/Library/Frameworks/System.framework/PrivateHeaders,
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+ };
+ name = Release;
+ };
+ 6EF877F023263D7000963DBB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 6EF877F123263D7000963DBB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
834F9B02212E560200F95A54 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1034,6 +1260,7 @@
COPY_HEADERS_UNIFDEF_FLAGS = "-UBUILD_FOR_OSX";
"COPY_HEADERS_UNIFDEF_FLAGS[sdk=macosx*]" = "-DBUILD_FOR_OSX";
COPY_PHASE_STRIP = NO;
+ DEPLOYMENT_LOCATION = YES;
DYLIB_CURRENT_VERSION = 228;
EXECUTABLE_PREFIX = lib;
GCC_CW_ASM_SYNTAX = NO;
@@ -1055,6 +1282,7 @@
OTHER_LDFLAGS = (
"-Xlinker",
"-not_for_dyld_shared_cache",
+ "-nodefaultlibs",
);
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/objc;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1070,6 +1298,7 @@
COPY_HEADERS_RUN_UNIFDEF = YES;
COPY_HEADERS_UNIFDEF_FLAGS = "-UBUILD_FOR_OSX";
"COPY_HEADERS_UNIFDEF_FLAGS[sdk=macosx*]" = "-DBUILD_FOR_OSX";
+ DEPLOYMENT_LOCATION = YES;
DYLIB_CURRENT_VERSION = 228;
EXECUTABLE_PREFIX = lib;
GCC_CW_ASM_SYNTAX = NO;
@@ -1090,6 +1319,7 @@
OTHER_LDFLAGS = (
"-Xlinker",
"-not_for_dyld_shared_cache",
+ "-nodefaultlibs",
);
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/objc;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1120,6 +1350,24 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 6EF877DD2325D62600963DBB /* Build configuration list for PBXNativeTarget "objcdt" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 6EF877DB2325D62600963DBB /* Debug */,
+ 6EF877DC2325D62600963DBB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 6EF877F223263D7000963DBB /* Build configuration list for PBXAggregateTarget "objc_executables" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 6EF877F023263D7000963DBB /* Debug */,
+ 6EF877F123263D7000963DBB /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
834F9B04212E560200F95A54 /* Build configuration list for PBXAggregateTarget "objc4_tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/objc4.plist b/objc4.plist
new file mode 100644
index 0000000..157aea8
--- /dev/null
+++ b/objc4.plist
@@ -0,0 +1,11 @@
+
+
+
+
+ preoptimizedCaches
+
+ Enabled
+
+
+
+
diff --git a/objcdt/json.h b/objcdt/json.h
new file mode 100644
index 0000000..95dbea2
--- /dev/null
+++ b/objcdt/json.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2019 Apple Inc. All Rights Reserved.
+*
+* @APPLE_LICENSE_HEADER_START@
+*
+* This file contains Original Code and/or Modifications of Original Code
+* as defined in and that are subject to the Apple Public Source License
+* Version 2.0 (the 'License'). You may not use this file except in
+* compliance with the License. Please obtain a copy of the License at
+* http://www.opensource.apple.com/apsl/ and read it before using this
+* file.
+*
+* The Original Code and all software distributed under the License are
+* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+* Please see the License for the specific language governing rights and
+* limitations under the License.
+*
+* @APPLE_LICENSE_HEADER_END@
+*/
+
+#ifndef _OBJC_OBJCDT_JSON_H_
+#define _OBJC_OBJCDT_JSON_H_
+
+#include
+#include
+#include
+#include
+
+namespace json {
+
+enum context: uint8_t {
+ root,
+ array_value,
+ object_value,
+ object_key,
+ done,
+};
+
+class writer {
+private:
+ FILE *_file;
+ context _context;
+ int _depth;
+ bool _needs_comma;
+
+ void begin_value(int sep = '\0');
+ void advance(context old);
+ void key(const char *key);
+
+public:
+
+ writer(FILE *f);
+ ~writer();
+
+ void object(std::function);
+ void object(const char *key, std::function);
+
+ void array(std::function);
+ void array(const char *key, std::function);
+
+ void boolean(bool value);
+ void boolean(const char *key, bool value);
+
+ void number(uint64_t value);
+ void number(const char *key, uint64_t value);
+
+ void string(const char *s);
+ void string(const char *key, const char *s);
+
+ __printflike(2, 3)
+ void stringf(const char *fmt, ...);
+
+ __printflike(3, 4)
+ void stringf(const char *key, const char *fmt, ...);
+};
+
+}
+
+#endif /* _OBJC_OBJCDT_JSON_H_ */
diff --git a/objcdt/json.mm b/objcdt/json.mm
new file mode 100644
index 0000000..7eb7488
--- /dev/null
+++ b/objcdt/json.mm
@@ -0,0 +1,234 @@
+/*
+* Copyright (c) 2019 Apple Inc. All Rights Reserved.
+*
+* @APPLE_LICENSE_HEADER_START@
+*
+* This file contains Original Code and/or Modifications of Original Code
+* as defined in and that are subject to the Apple Public Source License
+* Version 2.0 (the 'License'). You may not use this file except in
+* compliance with the License. Please obtain a copy of the License at
+* http://www.opensource.apple.com/apsl/ and read it before using this
+* file.
+*
+* The Original Code and all software distributed under the License are
+* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+* Please see the License for the specific language governing rights and
+* limitations under the License.
+*
+* @APPLE_LICENSE_HEADER_END@
+*/
+
+#include
+#include "json.h"
+
+namespace json {
+
+static bool
+context_is_value(context c)
+{
+ return c == root || c == array_value || c == object_value;
+}
+
+writer::writer(FILE *f)
+: _file(f)
+, _context(root)
+, _depth(0)
+, _needs_comma(false)
+{
+}
+
+writer::~writer()
+{
+ fputc('\n', _file);
+ fflush(_file);
+}
+
+void
+writer::begin_value(int sep)
+{
+ if (_needs_comma) {
+ _needs_comma = false;
+ if (sep) {
+ fprintf(_file, ", %c\n", sep);
+ return;
+ }
+ fputs(",\n", _file);
+ }
+ if (_context == array_value || _context == object_key) {
+ fprintf(_file, "%*s", _depth * 2, "");
+ }
+ if (sep) {
+ fprintf(_file, "%c\n", sep);
+ }
+}
+
+void
+writer::advance(context c)
+{
+ switch (c) {
+ case root:
+ _context = done;
+ _needs_comma = false;
+ break;
+ case array_value:
+ _context = array_value;
+ _needs_comma = true;
+ break;
+ case object_value:
+ _context = object_key;
+ _needs_comma = true;
+ break;
+ case object_key:
+ _context = object_value;
+ _needs_comma = false;
+ break;
+ case done:
+ assert(false);
+ break;
+ }
+}
+
+void
+writer::key(const char *key)
+{
+ assert(_context == object_key);
+
+ begin_value();
+ fprintf(_file, "\"%s\": ", key);
+ advance(_context);
+}
+
+void
+writer::object(std::function f)
+{
+ context old = _context;
+ assert(context_is_value(old));
+
+ begin_value('{');
+
+ _depth++;
+ _context = object_key;
+ _needs_comma = false;
+ f();
+
+ _depth--;
+ fprintf(_file, "\n%*s}", _depth * 2, "");
+ advance(old);
+}
+
+void
+writer::object(const char *k, std::function f)
+{
+ key(k);
+ object(f);
+}
+
+void
+writer::array(std::function f)
+{
+ context old = _context;
+ assert(context_is_value(old));
+
+ begin_value('[');
+
+ _depth++;
+ _context = array_value;
+ _needs_comma = false;
+ f();
+
+ _depth--;
+ fprintf(_file, "\n%*s]", _depth * 2, "");
+ advance(old);
+}
+
+void
+writer::array(const char *k, std::function f)
+{
+ key(k);
+ array(f);
+}
+
+void
+writer::boolean(bool value)
+{
+ assert(context_is_value(_context));
+ begin_value();
+ fputs(value ? "true" : "false", _file);
+ advance(_context);
+}
+
+void
+writer::boolean(const char *k, bool value)
+{
+ key(k);
+ boolean(value);
+}
+
+void
+writer::number(uint64_t value)
+{
+ assert(context_is_value(_context));
+ begin_value();
+ fprintf(_file, "%lld", value);
+ advance(_context);
+}
+
+void
+writer::number(const char *k, uint64_t value)
+{
+ key(k);
+ number(value);
+}
+
+void
+writer::string(const char *s)
+{
+ assert(context_is_value(_context));
+ begin_value();
+ fprintf(_file, "\"%s\"", s);
+ advance(_context);
+}
+
+void
+writer::string(const char *k, const char *s)
+{
+ key(k);
+ string(s);
+}
+
+void
+writer::stringf(const char *fmt, ...)
+{
+ va_list ap;
+
+ assert(context_is_value(_context));
+ begin_value();
+ fputc('"', _file);
+ va_start(ap, fmt);
+ vfprintf(_file, fmt, ap);
+ va_end(ap);
+ fputc('"', _file);
+ advance(_context);
+}
+
+void
+writer::stringf(const char *k, const char *fmt, ...)
+{
+ va_list ap;
+
+ key(k);
+
+ assert(context_is_value(_context));
+ begin_value();
+ fputc('"', _file);
+ va_start(ap, fmt);
+ vfprintf(_file, fmt, ap);
+ va_end(ap);
+ fputc('"', _file);
+ advance(_context);
+}
+
+} // json
diff --git a/objcdt/objcdt-entitlements.plist b/objcdt/objcdt-entitlements.plist
new file mode 100644
index 0000000..b7b4e6c
--- /dev/null
+++ b/objcdt/objcdt-entitlements.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ task_for_pid-allow
+
+ com.apple.system-task-ports
+
+
+
diff --git a/objcdt/objcdt.1 b/objcdt/objcdt.1
new file mode 100644
index 0000000..999a155
--- /dev/null
+++ b/objcdt/objcdt.1
@@ -0,0 +1,19 @@
+.\" Copyright (c) 2019, Apple Computer, Inc. All rights reserved.
+.\"
+.Dd September 9, 2019 \" DATE
+.Dt objcdt 1 \" Program name and manual section number
+.Os "OS X"
+.Sh NAME
+.Nm objcdt
+.Nd Tool to debug objective-C usage in live processes
+.Sh SYNOPSIS
+.Nm objcdt
+.Sh DESCRIPTION
+The
+.Nm
+utility is a small CLI with embedded help that can dump some information about
+the Objective-C runtime state in live processes.
+.Pp
+Help can be obtained using
+.Nm
+.Ar help
diff --git a/objcdt/objcdt.mm b/objcdt/objcdt.mm
new file mode 100644
index 0000000..eca5fa2
--- /dev/null
+++ b/objcdt/objcdt.mm
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2019 Apple Inc. All Rights Reserved.
+*
+* @APPLE_LICENSE_HEADER_START@
+*
+* This file contains Original Code and/or Modifications of Original Code
+* as defined in and that are subject to the Apple Public Source License
+* Version 2.0 (the 'License'). You may not use this file except in
+* compliance with the License. Please obtain a copy of the License at
+* http://www.opensource.apple.com/apsl/ and read it before using this
+* file.
+*
+* The Original Code and all software distributed under the License are
+* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+* Please see the License for the specific language governing rights and
+* limitations under the License.
+*
+* @APPLE_LICENSE_HEADER_END@
+*/
+
+#include "objc-private.h"
+#include "objc-ptrauth.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+int main(int argc, const char *argv[])
+{
+ return EX_UNAVAILABLE;
+}
diff --git a/objcrt/objcrt.vcproj b/objcrt/objcrt.vcproj
old mode 100644
new mode 100755
diff --git a/prebuild.bat b/prebuild.bat
old mode 100644
new mode 100755
diff --git a/test/gcfiles/x86_64-gconly b/runtime/.DS_Store
similarity index 62%
rename from test/gcfiles/x86_64-gconly
rename to runtime/.DS_Store
index fc907e7..5008ddf 100644
Binary files a/test/gcfiles/x86_64-gconly and b/runtime/.DS_Store differ
diff --git a/runtime/Messengers.subproj/objc-msg-arm.S b/runtime/Messengers.subproj/objc-msg-arm.S
index b1a9aec..4947209 100644
--- a/runtime/Messengers.subproj/objc-msg-arm.S
+++ b/runtime/Messengers.subproj/objc-msg-arm.S
@@ -222,6 +222,40 @@ LExit$0:
.endmacro
+//////////////////////////////////////////////////////////////////////
+//
+// SAVE_REGS
+//
+// Create a stack frame and save all argument registers in preparation
+// for a function call.
+//////////////////////////////////////////////////////////////////////
+
+.macro SAVE_REGS
+
+ stmfd sp!, {r0-r3,r7,lr}
+ add r7, sp, #16
+ sub sp, #8 // align stack
+ FP_SAVE
+
+.endmacro
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// RESTORE_REGS
+//
+// Restore all argument registers and pop the stack frame created by
+// SAVE_REGS.
+//////////////////////////////////////////////////////////////////////
+
+.macro RESTORE_REGS
+
+ FP_RESTORE
+ add sp, #8 // align stack
+ ldmfd sp!, {r0-r3,r7,lr}
+
+.endmacro
+
/////////////////////////////////////////////////////////////////////
//
// CacheLookup NORMAL|STRET
@@ -666,10 +700,7 @@ LNilReceiver:
.macro MethodTableLookup
- stmfd sp!, {r0-r3,r7,lr}
- add r7, sp, #16
- sub sp, #8 // align stack
- FP_SAVE
+ SAVE_REGS
// lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
.if $0 == NORMAL
@@ -680,7 +711,7 @@ LNilReceiver:
mov r1, r2 // selector
.endif
mov r2, r9 // class to search
- mov r3, #3 // LOOKUP_INITIALIZE | LOOKUP_INITIALIZE
+ mov r3, #3 // LOOKUP_INITIALIZE | LOOKUP_RESOLVER
blx _lookUpImpOrForward
mov r12, r0 // r12 = IMP
@@ -690,9 +721,7 @@ LNilReceiver:
tst r12, r12 // set ne for stret forwarding
.endif
- FP_RESTORE
- add sp, #8 // align stack
- ldmfd sp!, {r0-r3,r7,lr}
+ RESTORE_REGS
.endmacro
@@ -819,18 +848,55 @@ LNilReceiver:
ENTRY _method_invoke
+
+ // See if this is a small method.
+ lsls r12, r1, #31
+ bne.w L_method_invoke_small
+
+ // We can directly load the IMP from big methods.
// r1 is method triplet instead of SEL
ldr r12, [r1, #METHOD_IMP]
ldr r1, [r1, #METHOD_NAME]
bx r12
+
+L_method_invoke_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS
+ mov r0, r1
+ bl __method_getImplementationAndName
+ mov r12, r0
+ mov r9, r1
+ RESTORE_REGS
+ mov r1, r9
+ bx r12
+
+
END_ENTRY _method_invoke
ENTRY _method_invoke_stret
+
+ // See if this is a small method.
+ lsls r12, r2, #31
+ bne.w L_method_invoke_stret_small
+
+ // We can directly load the IMP from big methods.
// r2 is method triplet instead of SEL
ldr r12, [r2, #METHOD_IMP]
ldr r2, [r2, #METHOD_NAME]
bx r12
+
+L_method_invoke_stret_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS
+ mov r0, r2
+ bl __method_getImplementationAndName
+ mov r12, r0
+ mov r9, r1
+ RESTORE_REGS
+ mov r2, r9
+ bx r12
+
END_ENTRY _method_invoke_stret
diff --git a/runtime/Messengers.subproj/objc-msg-arm64.S b/runtime/Messengers.subproj/objc-msg-arm64.S
old mode 100644
new mode 100755
index 6bf3f29..7794ad5
--- a/runtime/Messengers.subproj/objc-msg-arm64.S
+++ b/runtime/Messengers.subproj/objc-msg-arm64.S
@@ -30,8 +30,19 @@
#include
#include "isa.h"
-#include "arm64-asm.h"
#include "objc-config.h"
+#include "arm64-asm.h"
+
+#if TARGET_OS_IPHONE && __LP64__
+ .section __TEXT,__objc_methname,cstring_literals
+l_MagicSelector: /* the shared cache builder knows about this value */
+ .byte 0xf0, 0x9f, 0xa4, 0xaf, 0
+
+ .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip
+ .p2align 3
+_MagicSelRef:
+ .quad l_MagicSelector
+#endif
.data
@@ -57,7 +68,6 @@
_objc_restartableRanges:
RestartableEntry _cache_getImp
RestartableEntry _objc_msgSend
- RestartableEntry _objc_msgSendSuper
RestartableEntry _objc_msgSendSuper2
RestartableEntry _objc_msgLookup
RestartableEntry _objc_msgLookupSuper2
@@ -81,13 +91,13 @@ _objc_restartableRanges:
/********************************************************************
- * GetClassFromIsa_p16 src
+ * GetClassFromIsa_p16 src, needs_auth, auth_address
* src is a raw isa field. Sets p16 to the corresponding class pointer.
* The raw isa might be an indexed isa to be decoded, or a
* packed isa that needs to be masked.
*
* On exit:
- * $0 is unchanged
+ * src is unchanged
* p16 is a class pointer
* x10 is clobbered
********************************************************************/
@@ -99,11 +109,11 @@ _objc_indexed_classes:
.fill ISA_INDEX_COUNT, PTRSIZE, 0
#endif
-.macro GetClassFromIsa_p16 /* src */
+.macro GetClassFromIsa_p16 src, needs_auth, auth_address /* note: auth_address is not required if !needs_auth */
#if SUPPORT_INDEXED_ISA
// Indexed isa
- mov p16, $0 // optimistically set dst = src
+ mov p16, \src // optimistically set dst = src
tbz p16, #ISA_INDEX_IS_NPI_BIT, 1f // done if not non-pointer isa
// isa in p16 is indexed
adrp x10, _objc_indexed_classes@PAGE
@@ -113,12 +123,15 @@ _objc_indexed_classes:
1:
#elif __LP64__
+.if \needs_auth == 0 // _cache_getImp takes an authed class already
+ mov p16, \src
+.else
// 64-bit packed isa
- and p16, $0, #ISA_MASK
-
+ ExtractISA p16, \src, \auth_address
+.endif
#else
// 32-bit raw isa
- mov p16, $0
+ mov p16, \src
#endif
@@ -169,9 +182,85 @@ LExit$0:
#define FrameWithNoSaves 0x04000000 // frame, no non-volatile saves
+#define MSGSEND 100
+#define METHOD_INVOKE 101
+
+//////////////////////////////////////////////////////////////////////
+//
+// SAVE_REGS
+//
+// Create a stack frame and save all argument registers in preparation
+// for a function call.
+//////////////////////////////////////////////////////////////////////
+
+.macro SAVE_REGS kind
+
+ // push frame
+ SignLR
+ stp fp, lr, [sp, #-16]!
+ mov fp, sp
+
+ // save parameter registers: x0..x8, q0..q7
+ sub sp, sp, #(10*8 + 8*16)
+ stp q0, q1, [sp, #(0*16)]
+ stp q2, q3, [sp, #(2*16)]
+ stp q4, q5, [sp, #(4*16)]
+ stp q6, q7, [sp, #(6*16)]
+ stp x0, x1, [sp, #(8*16+0*8)]
+ stp x2, x3, [sp, #(8*16+2*8)]
+ stp x4, x5, [sp, #(8*16+4*8)]
+ stp x6, x7, [sp, #(8*16+6*8)]
+.if \kind == MSGSEND
+ stp x8, x15, [sp, #(8*16+8*8)]
+ mov x16, x15 // stashed by CacheLookup, restore to x16
+.elseif \kind == METHOD_INVOKE
+ str x8, [sp, #(8*16+8*8)]
+.else
+.abort Unknown kind.
+.endif
+
+.endmacro
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// RESTORE_REGS
+//
+// Restore all argument registers and pop the stack frame created by
+// SAVE_REGS.
+//////////////////////////////////////////////////////////////////////
+
+.macro RESTORE_REGS kind
+
+ ldp q0, q1, [sp, #(0*16)]
+ ldp q2, q3, [sp, #(2*16)]
+ ldp q4, q5, [sp, #(4*16)]
+ ldp q6, q7, [sp, #(6*16)]
+ ldp x0, x1, [sp, #(8*16+0*8)]
+ ldp x2, x3, [sp, #(8*16+2*8)]
+ ldp x4, x5, [sp, #(8*16+4*8)]
+ ldp x6, x7, [sp, #(8*16+6*8)]
+.if \kind == MSGSEND
+ ldp x8, x16, [sp, #(8*16+8*8)]
+ orr x16, x16, #2 // for the sake of instrumentations, remember it was the slowpath
+.elseif \kind == METHOD_INVOKE
+ ldr x8, [sp, #(8*16+8*8)]
+.else
+.abort Unknown kind.
+.endif
+
+ mov sp, fp
+ ldp fp, lr, [sp], #16
+ AuthenticateLR
+
+.endmacro
+
+
/********************************************************************
*
- * CacheLookup NORMAL|GETIMP|LOOKUP
+ * CacheLookup NORMAL|GETIMP|LOOKUP MissLabelDynamic MissLabelConstant
+ *
+ * MissLabelConstant is only used for the GETIMP variant.
*
* Locate the implementation for a selector in a class method cache.
*
@@ -185,11 +274,27 @@ LExit$0:
* x16 = class to be searched
*
* Kills:
- * x9,x10,x11,x12, x17
+ * x9,x10,x11,x12,x13,x15,x17
+ *
+ * Untouched:
+ * x14
*
* On exit: (found) calls or returns IMP
* with x16 = class, x17 = IMP
+ * In LOOKUP mode, the two low bits are set to 0x3
+ * if we hit a constant cache (used in objc_trace)
* (not found) jumps to LCacheMiss
+ * with x15 = class
+ * For constant caches in LOOKUP mode, the low bit
+ * of x16 is set to 0x1 to indicate we had to fallback.
+ * In addition, when LCacheMiss is __objc_msgSend_uncached or
+ * __objc_msgLookup_uncached, 0x2 will be set in x16
+ * to remember we took the slowpath.
+ * So the two low bits of x16 on exit mean:
+ * 0: dynamic hit
+ * 1: fallback to the parent class, when there is a preoptimized cache
+ * 2: slowpath
+ * 3: preoptimized cache hit
*
********************************************************************/
@@ -197,60 +302,37 @@ LExit$0:
#define GETIMP 1
#define LOOKUP 2
-// CacheHit: x17 = cached IMP, x12 = address of cached IMP, x1 = SEL, x16 = isa
+// CacheHit: x17 = cached IMP, x10 = address of buckets, x1 = SEL, x16 = isa
.macro CacheHit
.if $0 == NORMAL
- TailCallCachedImp x17, x12, x1, x16 // authenticate and call imp
+ TailCallCachedImp x17, x10, x1, x16 // authenticate and call imp
.elseif $0 == GETIMP
mov p0, p17
cbz p0, 9f // don't ptrauth a nil imp
- AuthAndResignAsIMP x0, x12, x1, x16 // authenticate imp and re-sign as IMP
+ AuthAndResignAsIMP x0, x10, x1, x16 // authenticate imp and re-sign as IMP
9: ret // return IMP
.elseif $0 == LOOKUP
// No nil check for ptrauth: the caller would crash anyway when they
// jump to a nil IMP. We don't care if that jump also fails ptrauth.
- AuthAndResignAsIMP x17, x12, x1, x16 // authenticate imp and re-sign as IMP
+ AuthAndResignAsIMP x17, x10, x1, x16 // authenticate imp and re-sign as IMP
+ cmp x16, x15
+ cinc x16, x16, ne // x16 += 1 when x15 != x16 (for instrumentation ; fallback to the parent class)
ret // return imp via x17
.else
.abort oops
.endif
.endmacro
-.macro CheckMiss
- // miss if bucket->sel == 0
-.if $0 == GETIMP
- cbz p9, LGetImpMiss
-.elseif $0 == NORMAL
- cbz p9, __objc_msgSend_uncached
-.elseif $0 == LOOKUP
- cbz p9, __objc_msgLookup_uncached
-.else
-.abort oops
-.endif
-.endmacro
-
-.macro JumpMiss
-.if $0 == GETIMP
- b LGetImpMiss
-.elseif $0 == NORMAL
- b __objc_msgSend_uncached
-.elseif $0 == LOOKUP
- b __objc_msgLookup_uncached
-.else
-.abort oops
-.endif
-.endmacro
-
-.macro CacheLookup
+.macro CacheLookup Mode, Function, MissLabelDynamic, MissLabelConstant
//
// Restart protocol:
//
- // As soon as we're past the LLookupStart$1 label we may have loaded
- // an invalid cache pointer or mask.
+ // As soon as we're past the LLookupStart\Function label we may have
+ // loaded an invalid cache pointer or mask.
//
// When task_restartable_ranges_synchronize() is called,
- // (or when a signal hits us) before we're past LLookupEnd$1,
- // then our PC will be reset to LLookupRecover$1 which forcefully
+ // (or when a signal hits us) before we're past LLookupEnd\Function,
+ // then our PC will be reset to LLookupRecover\Function which forcefully
// jumps to the cache-miss codepath which have the following
// requirements:
//
@@ -263,70 +345,158 @@ LExit$0:
// - x16 contains the isa
// - other registers are set as per calling conventions
//
-LLookupStart$1:
+ mov x15, x16 // stash the original isa
+LLookupStart\Function:
// p1 = SEL, p16 = isa
- ldr p11, [x16, #CACHE] // p11 = mask|buckets
-
-#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
+#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS
+ ldr p10, [x16, #CACHE] // p10 = mask|buckets
+ lsr p11, p10, #48 // p11 = mask
+ and p10, p10, #0xffffffffffff // p10 = buckets
+ and w12, w1, w11 // x12 = _cmd & mask
+#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
+ ldr p11, [x16, #CACHE] // p11 = mask|buckets
+#if CONFIG_USE_PREOPT_CACHES
+#if __has_feature(ptrauth_calls)
+ tbnz p11, #0, LLookupPreopt\Function
+ and p10, p11, #0x0000ffffffffffff // p10 = buckets
+#else
+ and p10, p11, #0x0000fffffffffffe // p10 = buckets
+ tbnz p11, #0, LLookupPreopt\Function
+#endif
+ eor p12, p1, p1, LSR #7
+ and p12, p12, p11, LSR #48 // x12 = (_cmd ^ (_cmd >> 7)) & mask
+#else
and p10, p11, #0x0000ffffffffffff // p10 = buckets
and p12, p1, p11, LSR #48 // x12 = _cmd & mask
+#endif // CONFIG_USE_PREOPT_CACHES
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4
+ ldr p11, [x16, #CACHE] // p11 = mask|buckets
and p10, p11, #~0xf // p10 = buckets
and p11, p11, #0xf // p11 = maskShift
mov p12, #0xffff
- lsr p11, p12, p11 // p11 = mask = 0xffff >> p11
- and p12, p1, p11 // x12 = _cmd & mask
+ lsr p11, p12, p11 // p11 = mask = 0xffff >> p11
+ and p12, p1, p11 // x12 = _cmd & mask
#else
#error Unsupported cache mask storage for ARM64.
#endif
+ add p13, p10, p12, LSL #(1+PTRSHIFT)
+ // p13 = buckets + ((_cmd & mask) << (1+PTRSHIFT))
- add p12, p10, p12, LSL #(1+PTRSHIFT)
- // p12 = buckets + ((_cmd & mask) << (1+PTRSHIFT))
+ // do {
+1: ldp p17, p9, [x13], #-BUCKET_SIZE // {imp, sel} = *bucket--
+ cmp p9, p1 // if (sel != _cmd) {
+ b.ne 3f // scan more
+ // } else {
+2: CacheHit \Mode // hit: call or return imp
+ // }
+3: cbz p9, \MissLabelDynamic // if (sel == 0) goto Miss;
+ cmp p13, p10 // } while (bucket >= buckets)
+ b.hs 1b
- ldp p17, p9, [x12] // {imp, sel} = *bucket
-1: cmp p9, p1 // if (bucket->sel != _cmd)
- b.ne 2f // scan more
- CacheHit $0 // call or return imp
-
-2: // not hit: p12 = not-hit bucket
- CheckMiss $0 // miss if bucket->sel == 0
- cmp p12, p10 // wrap if bucket == buckets
- b.eq 3f
- ldp p17, p9, [x12, #-BUCKET_SIZE]! // {imp, sel} = *--bucket
- b 1b // loop
+ // wrap-around:
+ // p10 = first bucket
+ // p11 = mask (and maybe other bits on LP64)
+ // p12 = _cmd & mask
+ //
+ // A full cache can happen with CACHE_ALLOW_FULL_UTILIZATION.
+ // So stop when we circle back to the first probed bucket
+ // rather than when hitting the first bucket again.
+ //
+ // Note that we might probe the initial bucket twice
+ // when the first probed slot is the last entry.
-3: // wrap: p12 = first bucket, w11 = mask
-#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
- add p12, p12, p11, LSR #(48 - (1+PTRSHIFT))
- // p12 = buckets + (mask << 1+PTRSHIFT)
+
+#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS
+ add p13, p10, w11, UXTW #(1+PTRSHIFT)
+ // p13 = buckets + (mask << 1+PTRSHIFT)
+#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
+ add p13, p10, p11, LSR #(48 - (1+PTRSHIFT))
+ // p13 = buckets + (mask << 1+PTRSHIFT)
+ // see comment about maskZeroBits
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4
- add p12, p12, p11, LSL #(1+PTRSHIFT)
- // p12 = buckets + (mask << 1+PTRSHIFT)
+ add p13, p10, p11, LSL #(1+PTRSHIFT)
+ // p13 = buckets + (mask << 1+PTRSHIFT)
#else
#error Unsupported cache mask storage for ARM64.
#endif
+ add p12, p10, p12, LSL #(1+PTRSHIFT)
+ // p12 = first probed bucket
- // Clone scanning loop to miss instead of hang when cache is corrupt.
- // The slow path may detect any corruption and halt later.
+ // do {
+4: ldp p17, p9, [x13], #-BUCKET_SIZE // {imp, sel} = *bucket--
+ cmp p9, p1 // if (sel == _cmd)
+ b.eq 2b // goto hit
+ cmp p9, #0 // } while (sel != 0 &&
+ ccmp p13, p12, #0, ne // bucket > first_probed)
+ b.hi 4b
- ldp p17, p9, [x12] // {imp, sel} = *bucket
-1: cmp p9, p1 // if (bucket->sel != _cmd)
- b.ne 2f // scan more
- CacheHit $0 // call or return imp
-
-2: // not hit: p12 = not-hit bucket
- CheckMiss $0 // miss if bucket->sel == 0
- cmp p12, p10 // wrap if bucket == buckets
- b.eq 3f
- ldp p17, p9, [x12, #-BUCKET_SIZE]! // {imp, sel} = *--bucket
- b 1b // loop
+LLookupEnd\Function:
+LLookupRecover\Function:
+ b \MissLabelDynamic
-LLookupEnd$1:
-LLookupRecover$1:
-3: // double wrap
- JumpMiss $0
+#if CONFIG_USE_PREOPT_CACHES
+#if CACHE_MASK_STORAGE != CACHE_MASK_STORAGE_HIGH_16
+#error config unsupported
+#endif
+LLookupPreopt\Function:
+#if __has_feature(ptrauth_calls)
+ and p10, p11, #0x007ffffffffffffe // p10 = buckets
+ autdb x10, x16 // auth as early as possible
+#endif
+
+ // x12 = (_cmd - first_shared_cache_sel)
+ adrp x9, _MagicSelRef@PAGE
+ ldr p9, [x9, _MagicSelRef@PAGEOFF]
+ sub p12, p1, p9
+
+ // w9 = ((_cmd - first_shared_cache_sel) >> hash_shift & hash_mask)
+#if __has_feature(ptrauth_calls)
+ // bits 63..60 of x11 are the number of bits in hash_mask
+ // bits 59..55 of x11 is hash_shift
+
+ lsr x17, x11, #55 // w17 = (hash_shift, ...)
+ lsr w9, w12, w17 // >>= shift
+
+ lsr x17, x11, #60 // w17 = mask_bits
+ mov x11, #0x7fff
+ lsr x11, x11, x17 // p11 = mask (0x7fff >> mask_bits)
+ and x9, x9, x11 // &= mask
+#else
+ // bits 63..53 of x11 is hash_mask
+ // bits 52..48 of x11 is hash_shift
+ lsr x17, x11, #48 // w17 = (hash_shift, hash_mask)
+ lsr w9, w12, w17 // >>= shift
+ and x9, x9, x11, LSR #53 // &= mask
+#endif
+
+ ldr x17, [x10, x9, LSL #3] // x17 == sel_offs | (imp_offs << 32)
+ cmp x12, w17, uxtw
+
+.if \Mode == GETIMP
+ b.ne \MissLabelConstant // cache miss
+ sub x0, x16, x17, LSR #32 // imp = isa - imp_offs
+ SignAsImp x0
+ ret
+.else
+ b.ne 5f // cache miss
+ sub x17, x16, x17, LSR #32 // imp = isa - imp_offs
+.if \Mode == NORMAL
+ br x17
+.elseif \Mode == LOOKUP
+ orr x16, x16, #3 // for instrumentation, note that we hit a constant cache
+ SignAsImp x17
+ ret
+.else
+.abort unhandled mode \Mode
+.endif
+
+5: ldursw x9, [x10, #-8] // offset -8 is the fallback offset
+ add x16, x16, x9 // compute the fallback isa
+ b LLookupStart\Function // lookup again with a new isa
+.endif
+#endif // CONFIG_USE_PREOPT_CACHES
.endmacro
@@ -345,12 +515,37 @@ LLookupRecover$1:
#if SUPPORT_TAGGED_POINTERS
.data
.align 3
- .globl _objc_debug_taggedpointer_classes
-_objc_debug_taggedpointer_classes:
- .fill 16, 8, 0
.globl _objc_debug_taggedpointer_ext_classes
_objc_debug_taggedpointer_ext_classes:
.fill 256, 8, 0
+
+// Dispatch for split tagged pointers take advantage of the fact that
+// the extended tag classes array immediately precedes the standard
+// tag array. The .alt_entry directive ensures that the two stay
+// together. This is harmless when using non-split tagged pointers.
+ .globl _objc_debug_taggedpointer_classes
+ .alt_entry _objc_debug_taggedpointer_classes
+_objc_debug_taggedpointer_classes:
+ .fill 16, 8, 0
+
+// Look up the class for a tagged pointer in x0, placing it in x16.
+.macro GetTaggedClass
+
+ and x10, x0, #0x7 // x10 = small tag
+ asr x11, x0, #55 // x11 = large tag with 1s filling the top (because bit 63 is 1 on a tagged pointer)
+ cmp x10, #7 // tag == 7?
+ csel x12, x11, x10, eq // x12 = index in tagged pointer classes array, negative for extended tags.
+ // The extended tag array is placed immediately before the basic tag array
+ // so this looks into the right place either way. The sign extension done
+ // by the asr instruction produces the value extended_tag - 256, which produces
+ // the correct index in the extended tagged pointer classes array.
+
+ // x16 = _objc_debug_taggedpointer_classes[x12]
+ adrp x10, _objc_debug_taggedpointer_classes@PAGE
+ add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
+ ldr x16, [x10, x12, LSL #3]
+
+.endmacro
#endif
ENTRY _objc_msgSend
@@ -363,30 +558,15 @@ _objc_debug_taggedpointer_ext_classes:
b.eq LReturnZero
#endif
ldr p13, [x0] // p13 = isa
- GetClassFromIsa_p16 p13 // p16 = class
+ GetClassFromIsa_p16 p13, 1, x0 // p16 = class
LGetIsaDone:
// calls imp or objc_msgSend_uncached
- CacheLookup NORMAL, _objc_msgSend
+ CacheLookup NORMAL, _objc_msgSend, __objc_msgSend_uncached
#if SUPPORT_TAGGED_POINTERS
LNilOrTagged:
b.eq LReturnZero // nil check
-
- // tagged
- adrp x10, _objc_debug_taggedpointer_classes@PAGE
- add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
- ubfx x11, x0, #60, #4
- ldr x16, [x10, x11, LSL #3]
- adrp x10, _OBJC_CLASS_$___NSUnrecognizedTaggedPointer@PAGE
- add x10, x10, _OBJC_CLASS_$___NSUnrecognizedTaggedPointer@PAGEOFF
- cmp x10, x16
- b.ne LGetIsaDone
-
- // ext tagged
- adrp x10, _objc_debug_taggedpointer_ext_classes@PAGE
- add x10, x10, _objc_debug_taggedpointer_ext_classes@PAGEOFF
- ubfx x11, x0, #52, #8
- ldr x16, [x10, x11, LSL #3]
+ GetTaggedClass
b LGetIsaDone
// SUPPORT_TAGGED_POINTERS
#endif
@@ -412,37 +592,22 @@ LReturnZero:
b.eq LLookup_Nil
#endif
ldr p13, [x0] // p13 = isa
- GetClassFromIsa_p16 p13 // p16 = class
+ GetClassFromIsa_p16 p13, 1, x0 // p16 = class
LLookup_GetIsaDone:
// returns imp
- CacheLookup LOOKUP, _objc_msgLookup
+ CacheLookup LOOKUP, _objc_msgLookup, __objc_msgLookup_uncached
#if SUPPORT_TAGGED_POINTERS
LLookup_NilOrTagged:
b.eq LLookup_Nil // nil check
-
- // tagged
- adrp x10, _objc_debug_taggedpointer_classes@PAGE
- add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
- ubfx x11, x0, #60, #4
- ldr x16, [x10, x11, LSL #3]
- adrp x10, _OBJC_CLASS_$___NSUnrecognizedTaggedPointer@PAGE
- add x10, x10, _OBJC_CLASS_$___NSUnrecognizedTaggedPointer@PAGEOFF
- cmp x10, x16
- b.ne LLookup_GetIsaDone
-
-LLookup_ExtTag:
- adrp x10, _objc_debug_taggedpointer_ext_classes@PAGE
- add x10, x10, _objc_debug_taggedpointer_ext_classes@PAGEOFF
- ubfx x11, x0, #52, #8
- ldr x16, [x10, x11, LSL #3]
+ GetTaggedClass
b LLookup_GetIsaDone
// SUPPORT_TAGGED_POINTERS
#endif
LLookup_Nil:
- adrp x17, __objc_msgNil@PAGE
- add x17, x17, __objc_msgNil@PAGEOFF
+ adr x17, __objc_msgNil
+ SignAsImp x17
ret
END_ENTRY _objc_msgLookup
@@ -465,8 +630,7 @@ LLookup_Nil:
UNWIND _objc_msgSendSuper, NoFrame
ldp p0, p16, [x0] // p0 = real receiver, p16 = class
- // calls imp or objc_msgSend_uncached
- CacheLookup NORMAL, _objc_msgSendSuper
+ b L_objc_msgSendSuper2_body
END_ENTRY _objc_msgSendSuper
@@ -475,9 +639,18 @@ LLookup_Nil:
ENTRY _objc_msgSendSuper2
UNWIND _objc_msgSendSuper2, NoFrame
+#if __has_feature(ptrauth_calls)
+ ldp x0, x17, [x0] // x0 = real receiver, x17 = class
+ add x17, x17, #SUPERCLASS // x17 = &class->superclass
+ ldr x16, [x17] // x16 = class->superclass
+ AuthISASuper x16, x17, ISA_SIGNING_DISCRIMINATOR_CLASS_SUPERCLASS
+LMsgSendSuperResume:
+#else
ldp p0, p16, [x0] // p0 = real receiver, p16 = class
ldr p16, [x16, #SUPERCLASS] // p16 = class->superclass
- CacheLookup NORMAL, _objc_msgSendSuper2
+#endif
+L_objc_msgSendSuper2_body:
+ CacheLookup NORMAL, _objc_msgSendSuper2, __objc_msgSend_uncached
END_ENTRY _objc_msgSendSuper2
@@ -485,31 +658,24 @@ LLookup_Nil:
ENTRY _objc_msgLookupSuper2
UNWIND _objc_msgLookupSuper2, NoFrame
+#if __has_feature(ptrauth_calls)
+ ldp x0, x17, [x0] // x0 = real receiver, x17 = class
+ add x17, x17, #SUPERCLASS // x17 = &class->superclass
+ ldr x16, [x17] // x16 = class->superclass
+ AuthISASuper x16, x17, ISA_SIGNING_DISCRIMINATOR_CLASS_SUPERCLASS
+LMsgLookupSuperResume:
+#else
ldp p0, p16, [x0] // p0 = real receiver, p16 = class
ldr p16, [x16, #SUPERCLASS] // p16 = class->superclass
- CacheLookup LOOKUP, _objc_msgLookupSuper2
+#endif
+ CacheLookup LOOKUP, _objc_msgLookupSuper2, __objc_msgLookup_uncached
END_ENTRY _objc_msgLookupSuper2
.macro MethodTableLookup
- // push frame
- SignLR
- stp fp, lr, [sp, #-16]!
- mov fp, sp
-
- // save parameter registers: x0..x8, q0..q7
- sub sp, sp, #(10*8 + 8*16)
- stp q0, q1, [sp, #(0*16)]
- stp q2, q3, [sp, #(2*16)]
- stp q4, q5, [sp, #(4*16)]
- stp q6, q7, [sp, #(6*16)]
- stp x0, x1, [sp, #(8*16+0*8)]
- stp x2, x3, [sp, #(8*16+2*8)]
- stp x4, x5, [sp, #(8*16+4*8)]
- stp x6, x7, [sp, #(8*16+6*8)]
- str x8, [sp, #(8*16+8*8)]
+ SAVE_REGS MSGSEND
// lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
// receiver and selector already in x0 and x1
@@ -519,21 +685,8 @@ LLookup_Nil:
// IMP in x0
mov x17, x0
-
- // restore registers and return
- ldp q0, q1, [sp, #(0*16)]
- ldp q2, q3, [sp, #(2*16)]
- ldp q4, q5, [sp, #(4*16)]
- ldp q6, q7, [sp, #(6*16)]
- ldp x0, x1, [sp, #(8*16+0*8)]
- ldp x2, x3, [sp, #(8*16+2*8)]
- ldp x4, x5, [sp, #(8*16+4*8)]
- ldp x6, x7, [sp, #(8*16+6*8)]
- ldr x8, [sp, #(8*16+8*8)]
- mov sp, fp
- ldp fp, lr, [sp], #16
- AuthenticateLR
+ RESTORE_REGS MSGSEND
.endmacro
@@ -541,7 +694,7 @@ LLookup_Nil:
UNWIND __objc_msgSend_uncached, FrameWithNoSaves
// THIS IS NOT A CALLABLE C FUNCTION
- // Out-of-band p16 is the class to search
+ // Out-of-band p15 is the class to search
MethodTableLookup
TailCallFunctionPointer x17
@@ -553,7 +706,7 @@ LLookup_Nil:
UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
// THIS IS NOT A CALLABLE C FUNCTION
- // Out-of-band p16 is the class to search
+ // Out-of-band p15 is the class to search
MethodTableLookup
ret
@@ -563,13 +716,17 @@ LLookup_Nil:
STATIC_ENTRY _cache_getImp
- GetClassFromIsa_p16 p0
- CacheLookup GETIMP, _cache_getImp
+ GetClassFromIsa_p16 p0, 0
+ CacheLookup GETIMP, _cache_getImp, LGetImpMissDynamic, LGetImpMissConstant
-LGetImpMiss:
+LGetImpMissDynamic:
mov p0, #0
ret
+LGetImpMissConstant:
+ mov p0, p2
+ ret
+
END_ENTRY _cache_getImp
@@ -615,11 +772,37 @@ LGetImpMiss:
ENTRY _method_invoke
+
+ // See if this is a small method.
+ tbnz p1, #0, L_method_invoke_small
+
+ // We can directly load the IMP from big methods.
// x1 is method triplet instead of SEL
add p16, p1, #METHOD_IMP
ldr p17, [x16]
ldr p1, [x1, #METHOD_NAME]
TailCallMethodListImp x17, x16
+
+L_method_invoke_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS METHOD_INVOKE
+ mov p0, p1
+ bl __method_getImplementationAndName
+ // ARM64_32 packs both return values into x0, with SEL in the high bits and IMP in the low.
+ // ARM64 just returns them in x0 and x1.
+ mov x17, x0
+#if __LP64__
+ mov x16, x1
+#endif
+ RESTORE_REGS METHOD_INVOKE
+#if __LP64__
+ mov x1, x16
+#else
+ lsr x1, x17, #32
+ mov w17, w17
+#endif
+ TailCallFunctionPointer x17
+
END_ENTRY _method_invoke
#endif
diff --git a/runtime/Messengers.subproj/objc-msg-simulator-i386.S b/runtime/Messengers.subproj/objc-msg-simulator-i386.S
index 727b983..914a9ac 100644
--- a/runtime/Messengers.subproj/objc-msg-simulator-i386.S
+++ b/runtime/Messengers.subproj/objc-msg-simulator-i386.S
@@ -192,6 +192,47 @@ LExit$0:
#define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
+//////////////////////////////////////////////////////////////////////
+//
+// SAVE_REGS
+//
+// Create a stack frame and save all argument registers in preparation
+// for a function call.
+//////////////////////////////////////////////////////////////////////
+
+.macro SAVE_REGS
+
+ pushl %ebp
+ movl %esp, %ebp
+
+ subl $$(8+5*16), %esp
+
+ movdqa %xmm3, 4*16(%esp)
+ movdqa %xmm2, 3*16(%esp)
+ movdqa %xmm1, 2*16(%esp)
+ movdqa %xmm0, 1*16(%esp)
+
+.endmacro
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// RESTORE_REGS
+//
+// Restore all argument registers and pop the stack frame created by
+// SAVE_REGS.
+//////////////////////////////////////////////////////////////////////
+
+.macro RESTORE_REGS
+
+ movdqa 4*16(%esp), %xmm3
+ movdqa 3*16(%esp), %xmm2
+ movdqa 2*16(%esp), %xmm1
+ movdqa 1*16(%esp), %xmm0
+
+ leave
+
+.endmacro
/////////////////////////////////////////////////////////////////////
//
// CacheLookup return-type, caller
@@ -314,10 +355,7 @@ LExit$0:
/////////////////////////////////////////////////////////////////////
.macro MethodTableLookup
- pushl %ebp
- movl %esp, %ebp
-
- subl $$(8+5*16), %esp
+ SAVE_REGS
.if $0 == NORMAL
movl self+4(%ebp), %eax
@@ -327,11 +365,6 @@ LExit$0:
movl selector_stret+4(%ebp), %ecx
.endif
- movdqa %xmm3, 4*16(%esp)
- movdqa %xmm2, 3*16(%esp)
- movdqa %xmm1, 2*16(%esp)
- movdqa %xmm0, 1*16(%esp)
-
// lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
movl $$3, 12(%esp) // LOOKUP_INITIALIZE | LOOKUP_RESOLVER
movl %edx, 8(%esp) // class
@@ -341,18 +374,13 @@ LExit$0:
// imp in eax
- movdqa 4*16(%esp), %xmm3
- movdqa 3*16(%esp), %xmm2
- movdqa 2*16(%esp), %xmm1
- movdqa 1*16(%esp), %xmm0
-
.if $0 == NORMAL
test %eax, %eax // set ne for stret forwarding
.else
cmp %eax, %eax // set eq for nonstret forwarding
.endif
- leave
+ RESTORE_REGS
.endmacro
@@ -906,23 +934,55 @@ L_forward_stret_handler:
ENTRY _method_invoke
+ // See if this is a small method.
+ testb $1, selector(%esp)
+ jnz L_method_invoke_small
+
+ // We can directly load the IMP from big methods.
movl selector(%esp), %ecx
movl method_name(%ecx), %edx
movl method_imp(%ecx), %eax
movl %edx, selector(%esp)
jmp *%eax
-
+
+L_method_invoke_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS
+
+ movl selector+4(%ebp), %eax
+ movl %eax, 0(%esp)
+ call __method_getImplementationAndName
+ RESTORE_REGS
+ movl %edx, selector(%esp)
+ jmp *%eax
+
END_ENTRY _method_invoke
ENTRY _method_invoke_stret
+ // See if this is a small method.
+ testb $1, selector_stret(%esp)
+ jnz L_method_invoke_stret_small
+
+ // We can directly load the IMP from big methods.
movl selector_stret(%esp), %ecx
movl method_name(%ecx), %edx
movl method_imp(%ecx), %eax
movl %edx, selector_stret(%esp)
jmp *%eax
+L_method_invoke_stret_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS
+
+ movl selector_stret+4(%ebp), %eax
+ movl %eax, 0(%esp)
+ call __method_getImplementationAndName
+ RESTORE_REGS
+ movl %edx, selector_stret(%esp)
+ jmp *%eax
+
END_ENTRY _method_invoke_stret
diff --git a/runtime/Messengers.subproj/objc-msg-simulator-x86_64.S b/runtime/Messengers.subproj/objc-msg-simulator-x86_64.S
index a5410c4..402b97d 100644
--- a/runtime/Messengers.subproj/objc-msg-simulator-x86_64.S
+++ b/runtime/Messengers.subproj/objc-msg-simulator-x86_64.S
@@ -22,7 +22,7 @@
*/
#include
-#if __x86_64__ && TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC
+#if __x86_64__ && TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST
/********************************************************************
********************************************************************
@@ -93,6 +93,7 @@ _objc_restartableRanges:
#define a2b sil
#define a3 rdx
#define a3d edx
+#define a3b dl
#define a4 rcx
#define a4d ecx
#define a5 r8
@@ -132,6 +133,10 @@ _objc_restartableRanges:
#define GETIMP 101
#define LOOKUP 102
+#define MSGSEND 200
+#define METHOD_INVOKE 201
+#define METHOD_INVOKE_STRET 202
+
/********************************************************************
*
@@ -212,6 +217,88 @@ LExit$0:
#define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
+//////////////////////////////////////////////////////////////////////
+//
+// SAVE_REGS
+//
+// Create a stack frame and save all argument registers in preparation
+// for a function call.
+//////////////////////////////////////////////////////////////////////
+
+.macro SAVE_REGS kind
+
+.if \kind != MSGSEND && \kind != METHOD_INVOKE && \kind != METHOD_INVOKE_STRET
+.abort Unknown kind.
+.endif
+ push %rbp
+ mov %rsp, %rbp
+
+ sub $0x80, %rsp
+
+ movdqa %xmm0, -0x80(%rbp)
+ push %rax // might be xmm parameter count
+ movdqa %xmm1, -0x70(%rbp)
+ push %a1
+ movdqa %xmm2, -0x60(%rbp)
+.if \kind == MSGSEND || \kind == METHOD_INVOKE_STRET
+ push %a2
+.endif
+ movdqa %xmm3, -0x50(%rbp)
+.if \kind == MSGSEND || \kind == METHOD_INVOKE
+ push %a3
+.endif
+ movdqa %xmm4, -0x40(%rbp)
+ push %a4
+ movdqa %xmm5, -0x30(%rbp)
+ push %a5
+ movdqa %xmm6, -0x20(%rbp)
+ push %a6
+ movdqa %xmm7, -0x10(%rbp)
+.if \kind == MSGSEND
+ push %r10
+.endif
+
+.endmacro
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// RESTORE_REGS
+//
+// Restore all argument registers and pop the stack frame created by
+// SAVE_REGS.
+//////////////////////////////////////////////////////////////////////
+
+.macro RESTORE_REGS kind
+
+.if \kind == MSGSEND
+ pop %r10
+ orq $2, %r10 // for the sake of instrumentations, remember it was the slowpath
+.endif
+ movdqa -0x80(%rbp), %xmm0
+ pop %a6
+ movdqa -0x70(%rbp), %xmm1
+ pop %a5
+ movdqa -0x60(%rbp), %xmm2
+ pop %a4
+ movdqa -0x50(%rbp), %xmm3
+.if \kind == MSGSEND || \kind == METHOD_INVOKE
+ pop %a3
+.endif
+ movdqa -0x40(%rbp), %xmm4
+.if \kind == MSGSEND || \kind == METHOD_INVOKE_STRET
+ pop %a2
+.endif
+ movdqa -0x30(%rbp), %xmm5
+ pop %a1
+ movdqa -0x20(%rbp), %xmm6
+ pop %rax
+ movdqa -0x10(%rbp), %xmm7
+ leave
+
+.endmacro
+
+
/////////////////////////////////////////////////////////////////////
//
// CacheLookup return-type, caller
@@ -347,26 +434,7 @@ LExit$0:
.macro MethodTableLookup
- push %rbp
- mov %rsp, %rbp
-
- sub $$0x80+8, %rsp // +8 for alignment
-
- movdqa %xmm0, -0x80(%rbp)
- push %rax // might be xmm parameter count
- movdqa %xmm1, -0x70(%rbp)
- push %a1
- movdqa %xmm2, -0x60(%rbp)
- push %a2
- movdqa %xmm3, -0x50(%rbp)
- push %a3
- movdqa %xmm4, -0x40(%rbp)
- push %a4
- movdqa %xmm5, -0x30(%rbp)
- push %a5
- movdqa %xmm6, -0x20(%rbp)
- push %a6
- movdqa %xmm7, -0x10(%rbp)
+ SAVE_REGS MSGSEND
// lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
.if $0 == NORMAL
@@ -383,29 +451,13 @@ LExit$0:
// IMP is now in %rax
movq %rax, %r11
- movdqa -0x80(%rbp), %xmm0
- pop %a6
- movdqa -0x70(%rbp), %xmm1
- pop %a5
- movdqa -0x60(%rbp), %xmm2
- pop %a4
- movdqa -0x50(%rbp), %xmm3
- pop %a3
- movdqa -0x40(%rbp), %xmm4
- pop %a2
- movdqa -0x30(%rbp), %xmm5
- pop %a1
- movdqa -0x20(%rbp), %xmm6
- pop %rax
- movdqa -0x10(%rbp), %xmm7
+ RESTORE_REGS MSGSEND
.if $0 == NORMAL
test %r11, %r11 // set ne for stret forwarding
.else
cmp %r11, %r11 // set eq for nonstret forwarding
.endif
-
- leave
.endmacro
@@ -1104,19 +1156,49 @@ LCacheMiss:
ENTRY _method_invoke
+ // See if this is a small method.
+ testb $1, %a2b
+ jnz L_method_invoke_small
+
+ // We can directly load the IMP from big methods.
movq method_imp(%a2), %r11
movq method_name(%a2), %a2
jmp *%r11
-
+
+L_method_invoke_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS METHOD_INVOKE
+ movq %a2, %a1
+ call __method_getImplementationAndName
+ movq %rdx, %a2
+ movq %rax, %r11
+ RESTORE_REGS METHOD_INVOKE
+ jmp *%r11
+
END_ENTRY _method_invoke
ENTRY _method_invoke_stret
+ // See if this is a small method.
+ testb $1, %a3b
+ jnz L_method_invoke_stret_small
+
+ // We can directly load the IMP from big methods.
movq method_imp(%a3), %r11
movq method_name(%a3), %a3
jmp *%r11
-
+
+L_method_invoke_stret_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS METHOD_INVOKE_STRET
+ movq %a3, %a1
+ call __method_getImplementationAndName
+ movq %rdx, %a3
+ movq %rax, %r11
+ RESTORE_REGS METHOD_INVOKE_STRET
+ jmp *%r11
+
END_ENTRY _method_invoke_stret
diff --git a/runtime/Messengers.subproj/objc-msg-x86_64.S b/runtime/Messengers.subproj/objc-msg-x86_64.S
index 8fc6d48..0b8eff7 100644
--- a/runtime/Messengers.subproj/objc-msg-x86_64.S
+++ b/runtime/Messengers.subproj/objc-msg-x86_64.S
@@ -22,7 +22,7 @@
*/
#include
-#if __x86_64__ && !(TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC)
+#if __x86_64__ && !(TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST)
#include "isa.h"
@@ -102,6 +102,7 @@ _objc_restartableRanges:
#define a2b sil
#define a3 rdx
#define a3d edx
+#define a3b dl
#define a4 rcx
#define a4d ecx
#define a5 r8
@@ -138,6 +139,10 @@ _objc_restartableRanges:
#define GETIMP 101
#define LOOKUP 102
+#define MSGSEND 200
+#define METHOD_INVOKE 201
+#define METHOD_INVOKE_STRET 202
+
/********************************************************************
*
@@ -218,6 +223,88 @@ LExit$0:
#define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
+//////////////////////////////////////////////////////////////////////
+//
+// SAVE_REGS
+//
+// Create a stack frame and save all argument registers in preparation
+// for a function call.
+//////////////////////////////////////////////////////////////////////
+
+.macro SAVE_REGS kind
+
+.if \kind != MSGSEND && \kind != METHOD_INVOKE && \kind != METHOD_INVOKE_STRET
+.abort Unknown kind.
+.endif
+ push %rbp
+ mov %rsp, %rbp
+
+ sub $0x80, %rsp
+
+ movdqa %xmm0, -0x80(%rbp)
+ push %rax // might be xmm parameter count
+ movdqa %xmm1, -0x70(%rbp)
+ push %a1
+ movdqa %xmm2, -0x60(%rbp)
+.if \kind == MSGSEND || \kind == METHOD_INVOKE_STRET
+ push %a2
+.endif
+ movdqa %xmm3, -0x50(%rbp)
+.if \kind == MSGSEND || \kind == METHOD_INVOKE
+ push %a3
+.endif
+ movdqa %xmm4, -0x40(%rbp)
+ push %a4
+ movdqa %xmm5, -0x30(%rbp)
+ push %a5
+ movdqa %xmm6, -0x20(%rbp)
+ push %a6
+ movdqa %xmm7, -0x10(%rbp)
+.if \kind == MSGSEND
+ push %r10
+.endif
+
+.endmacro
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// RESTORE_REGS
+//
+// Restore all argument registers and pop the stack frame created by
+// SAVE_REGS.
+//////////////////////////////////////////////////////////////////////
+
+.macro RESTORE_REGS kind
+
+.if \kind == MSGSEND
+ pop %r10
+ orq $2, %r10 // for the sake of instrumentations, remember it was the slowpath
+.endif
+ movdqa -0x80(%rbp), %xmm0
+ pop %a6
+ movdqa -0x70(%rbp), %xmm1
+ pop %a5
+ movdqa -0x60(%rbp), %xmm2
+ pop %a4
+ movdqa -0x50(%rbp), %xmm3
+.if \kind == MSGSEND || \kind == METHOD_INVOKE
+ pop %a3
+.endif
+ movdqa -0x40(%rbp), %xmm4
+.if \kind == MSGSEND || \kind == METHOD_INVOKE_STRET
+ pop %a2
+.endif
+ movdqa -0x30(%rbp), %xmm5
+ pop %a1
+ movdqa -0x20(%rbp), %xmm6
+ pop %rax
+ movdqa -0x10(%rbp), %xmm7
+ leave
+
+.endmacro
+
+
/////////////////////////////////////////////////////////////////////
//
// CacheLookup return-type, caller, function
@@ -382,26 +469,7 @@ LLookupEnd$2:
.macro MethodTableLookup
- push %rbp
- mov %rsp, %rbp
-
- sub $$0x80+8, %rsp // +8 for alignment
-
- movdqa %xmm0, -0x80(%rbp)
- push %rax // might be xmm parameter count
- movdqa %xmm1, -0x70(%rbp)
- push %a1
- movdqa %xmm2, -0x60(%rbp)
- push %a2
- movdqa %xmm3, -0x50(%rbp)
- push %a3
- movdqa %xmm4, -0x40(%rbp)
- push %a4
- movdqa %xmm5, -0x30(%rbp)
- push %a5
- movdqa %xmm6, -0x20(%rbp)
- push %a6
- movdqa %xmm7, -0x10(%rbp)
+ SAVE_REGS MSGSEND
// lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
.if $0 == NORMAL
@@ -418,29 +486,13 @@ LLookupEnd$2:
// IMP is now in %rax
movq %rax, %r11
- movdqa -0x80(%rbp), %xmm0
- pop %a6
- movdqa -0x70(%rbp), %xmm1
- pop %a5
- movdqa -0x60(%rbp), %xmm2
- pop %a4
- movdqa -0x50(%rbp), %xmm3
- pop %a3
- movdqa -0x40(%rbp), %xmm4
- pop %a2
- movdqa -0x30(%rbp), %xmm5
- pop %a1
- movdqa -0x20(%rbp), %xmm6
- pop %rax
- movdqa -0x10(%rbp), %xmm7
+ RESTORE_REGS MSGSEND
.if $0 == NORMAL
test %r11, %r11 // set ne for nonstret forwarding
.else
cmp %r11, %r11 // set eq for stret forwarding
.endif
-
- leave
.endmacro
@@ -1216,19 +1268,49 @@ LCacheMiss_objc_msgLookupSuper2_stret:
ENTRY _method_invoke
+ // See if this is a small method.
+ testb $1, %a2b
+ jnz L_method_invoke_small
+
+ // We can directly load the IMP from big methods.
movq method_imp(%a2), %r11
movq method_name(%a2), %a2
jmp *%r11
-
+
+L_method_invoke_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS METHOD_INVOKE
+ movq %a2, %a1
+ call __method_getImplementationAndName
+ movq %rdx, %a2
+ movq %rax, %r11
+ RESTORE_REGS METHOD_INVOKE
+ jmp *%r11
+
END_ENTRY _method_invoke
ENTRY _method_invoke_stret
+ // See if this is a small method.
+ testb $1, %a3b
+ jnz L_method_invoke_stret_small
+
+ // We can directly load the IMP from big methods.
movq method_imp(%a3), %r11
movq method_name(%a3), %a3
jmp *%r11
-
+
+L_method_invoke_stret_small:
+ // Small methods require a call to handle swizzling.
+ SAVE_REGS METHOD_INVOKE_STRET
+ movq %a3, %a1
+ call __method_getImplementationAndName
+ movq %rdx, %a3
+ movq %rax, %r11
+ RESTORE_REGS METHOD_INVOKE_STRET
+ jmp *%r11
+
END_ENTRY _method_invoke_stret
diff --git a/runtime/NSObject-internal.h b/runtime/NSObject-internal.h
index c23fbc2..978799a 100644
--- a/runtime/NSObject-internal.h
+++ b/runtime/NSObject-internal.h
@@ -123,6 +123,16 @@ struct magic_t {
class AutoreleasePoolPage;
struct AutoreleasePoolPageData
{
+#if SUPPORT_AUTORELEASEPOOL_DEDUP_PTRS
+ struct AutoreleasePoolEntry {
+ uintptr_t ptr: 48;
+ uintptr_t count: 16;
+
+ static const uintptr_t maxCount = 65535; // 2^16 - 1
+ };
+ static_assert((AutoreleasePoolEntry){ .ptr = MACH_VM_MAX_ADDRESS }.ptr == MACH_VM_MAX_ADDRESS, "MACH_VM_MAX_ADDRESS doesn't fit into AutoreleasePoolEntry::ptr!");
+#endif
+
magic_t const magic;
__unsafe_unretained id *next;
pthread_t const thread;
diff --git a/runtime/NSObject.mm b/runtime/NSObject.mm
index 982e4bb..6d2e14f 100644
--- a/runtime/NSObject.mm
+++ b/runtime/NSObject.mm
@@ -39,6 +39,12 @@
#include