]> git.saurik.com Git - apple/objc4.git/blobdiff - runtime/objc-block-trampolines.mm
objc4-818.2.tar.gz
[apple/objc4.git] / runtime / objc-block-trampolines.mm
index 9dea652cd0067fe37504468c9590af5ba4e8b4a9..f905d35cd08fa2bf9d048e3b038f64351f554608 100644 (file)
 #   define TrampolinePtrauth
 #endif
 
+// A page of trampolines is as big as the maximum supported page size
+// everywhere except i386. i386 only exists for the watch simulator
+// now, and we know it really only has 4kB pages. Also see comments
+// below about PAGE_SIZE and PAGE_MAX_SIZE.
+#ifdef __i386__
+#define TRAMPOLINE_PAGE_SIZE PAGE_MIN_SIZE
+#else
+#define TRAMPOLINE_PAGE_SIZE PAGE_MAX_SIZE
+#endif
+
 class TrampolinePointerWrapper {
     struct TrampolinePointers {
         class TrampolineAddress {
@@ -103,22 +113,22 @@ class TrampolinePointerWrapper {
 
         void check() {
 #if DEBUG
-            ASSERT(impl.address() == textSegment + PAGE_MAX_SIZE);
-            ASSERT(impl.address() % PAGE_SIZE == 0);  // not PAGE_MAX_SIZE
-            assert(impl.address() + PAGE_MAX_SIZE ==
+            ASSERT(impl.address() == textSegment + TRAMPOLINE_PAGE_SIZE);
+            ASSERT(impl.address() % PAGE_SIZE == 0);  // not TRAMPOLINE_PAGE_SIZE
+            ASSERT(impl.address() + TRAMPOLINE_PAGE_SIZE ==
                    last.address() + SLOT_SIZE);
             ASSERT(last.address()+8 < textSegment + textSegmentSize);
             ASSERT((last.address() - start.address()) % SLOT_SIZE == 0);
 # if SUPPORT_STRET
-            ASSERT(impl_stret.address() == textSegment + 2*PAGE_MAX_SIZE);
-            ASSERT(impl_stret.address() % PAGE_SIZE == 0);  // not PAGE_MAX_SIZE
-            assert(impl_stret.address() + PAGE_MAX_SIZE ==
+            ASSERT(impl_stret.address() == textSegment + 2*TRAMPOLINE_PAGE_SIZE);
+            ASSERT(impl_stret.address() % PAGE_SIZE == 0);  // not TRAMPOLINE_PAGE_SIZE
+            ASSERT(impl_stret.address() + TRAMPOLINE_PAGE_SIZE ==
                    last_stret.address() + SLOT_SIZE);
-            assert(start.address() - impl.address() ==
+            ASSERT(start.address() - impl.address() ==
                    start_stret.address() - impl_stret.address());
-            assert(last_stret.address() + SLOT_SIZE <
+            ASSERT(last_stret.address() + SLOT_SIZE <
                    textSegment + textSegmentSize);
-            assert((last_stret.address() - start_stret.address())
+            ASSERT((last_stret.address() - start_stret.address())
                    % SLOT_SIZE == 0);
 # endif
 #endif
@@ -178,8 +188,7 @@ public:
     uintptr_t textSegment() { return get()->textSegment; }
     uintptr_t textSegmentSize() { return get()->textSegmentSize; }
 
-    // See comments below about PAGE_SIZE and PAGE_MAX_SIZE.
-    uintptr_t dataSize() { return PAGE_MAX_SIZE; }
+    uintptr_t dataSize() { return TRAMPOLINE_PAGE_SIZE; }
 
     uintptr_t impl() { return get()->impl.address(); }
     uintptr_t start() { return get()->start.address(); }
@@ -202,11 +211,13 @@ typedef enum {
 // We must take care with our data layout on architectures that support 
 // multiple page sizes.
 // 
-// The trampoline template in __TEXT is sized and aligned with PAGE_MAX_SIZE.
-// On some platforms this requires additional linker flags.
+// The trampoline template in __TEXT is sized and aligned with PAGE_MAX_SIZE,
+// except on i386 which is a weird special case that uses PAGE_MIN_SIZE.
+// The TRAMPOLINE_PAGE_SIZE macro handles this difference. On some platforms,
+// aligning to PAGE_MAX_SIZE requires additional linker flags.
 // 
-// When we allocate a page group, we use PAGE_MAX_SIZE size. 
-// This allows trampoline code to find its data by subtracting PAGE_MAX_SIZE.
+// When we allocate a page group, we use TRAMPOLINE_PAGE_SIZE size.
+// This allows trampoline code to find its data by subtracting TRAMPOLINE_PAGE_SIZE.
 // 
 // When we allocate a page group, we use the process's page alignment. 
 // This simplifies allocation because we don't need to force greater than 
@@ -231,14 +242,14 @@ struct TrampolineBlockPageGroup
     
     // Payload data: block pointers and free list.
     // Bytes parallel with trampoline header code are the fields above or unused
-    // uint8_t payloads[PAGE_MAX_SIZE - sizeof(TrampolineBlockPageGroup)] 
+    // uint8_t payloads[TRAMPOLINE_PAGE_SIZE - sizeof(TrampolineBlockPageGroup)]
 
     // Code: Mach-O header, then trampoline header followed by trampolines.
     // On platforms with struct return we have non-stret trampolines and
     //     stret trampolines. The stret and non-stret trampolines at a given
     //     index share the same data page.
-    // uint8_t macho[PAGE_MAX_SIZE];
-    // uint8_t trampolines[ArgumentModeCount][PAGE_MAX_SIZE];
+    // uint8_t macho[TRAMPOLINE_PAGE_SIZE];
+    // uint8_t trampolines[ArgumentModeCount][TRAMPOLINE_PAGE_SIZE];
     
     // Per-trampoline block data format:
     // initial value is 0 while page data is filled sequentially 
@@ -280,7 +291,7 @@ struct TrampolineBlockPageGroup
         // Skip over the data area, one page of Mach-O headers,
         // and one text page for each mode before this one.
         return (uintptr_t)this + Trampolines.dataSize() +
-            PAGE_MAX_SIZE * (1 + aMode);
+            TRAMPOLINE_PAGE_SIZE * (1 + aMode);
     }
     
     IMP trampoline(int aMode, uintptr_t index) {