restartableRangesSynchronizeStress.m 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // TEST_CONFIG OS=macosx,iphoneos,tvos,watchos
  2. // This test checks that objc_msgSend's recovery path works correctly.
  3. // It continuously runs msgSend on some background threads, then
  4. // triggers the recovery path constantly as a stress test.
  5. #include "test.h"
  6. #include "testroot.i"
  7. #include <dispatch/dispatch.h>
  8. struct Big {
  9. uintptr_t a, b, c, d, e, f, g;
  10. };
  11. @interface C1: TestRoot
  12. @end
  13. @implementation C1
  14. - (id)idret { return nil; }
  15. - (double)fpret { return 0.0; }
  16. - (long double)lfpret { return 0.0; }
  17. - (struct Big)stret { return (struct Big){}; }
  18. @end
  19. @interface C2: C1
  20. @end
  21. @implementation C2
  22. - (id)idret { return [super idret]; }
  23. - (double)fpret { return [super fpret]; }
  24. - (long double)lfpret { return [super lfpret]; }
  25. - (struct Big)stret { return [super stret]; }
  26. @end
  27. EXTERN_C kern_return_t task_restartable_ranges_synchronize(task_t task);
  28. EXTERN_C void sendWithMsgLookup(id self, SEL _cmd);
  29. #if defined(__arm64__) && !__has_feature(ptrauth_calls)
  30. asm(
  31. "_sendWithMsgLookup: \n"
  32. " stp fp, lr, [sp, #-16]! \n"
  33. " mov fp, sp \n"
  34. " bl _objc_msgLookup \n"
  35. " mov sp, fp \n"
  36. " ldp fp, lr, [sp], #16 \n"
  37. " br x17 \n"
  38. );
  39. #elif defined(__x86_64__)
  40. asm(
  41. "_sendWithMsgLookup: \n"
  42. " pushq %rbp \n"
  43. " movq %rsp, %rbp \n"
  44. " callq _objc_msgLookup \n"
  45. " popq %rbp \n"
  46. " jmpq *%r11 \n"
  47. );
  48. #else
  49. // Just skip it.
  50. void sendWithMsgLookup(id self __unused, SEL _cmd __unused) {}
  51. #endif
  52. int main() {
  53. id obj = [C2 new];
  54. for(int i = 0; i < 2; i++) {
  55. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  56. while(1) {
  57. [obj idret];
  58. [obj fpret];
  59. [obj lfpret];
  60. [obj stret];
  61. sendWithMsgLookup(obj, @selector(idret));
  62. }
  63. });
  64. }
  65. for(int i = 0; i < 1000000; i++) {
  66. task_restartable_ranges_synchronize(mach_task_self());;
  67. }
  68. succeed(__FILE__);
  69. }