Differences From Artifact [6a15e61b81]:
- File src/runtime/autorelease.m — part of check-in [f2fe8f96d5] at 2020-01-02 22:16:48 on branch trunk — Move autorelease pools to runtime (user: js, size: 3192) [annotate] [blame] [check-ins using] [more...]
To Artifact [99568ccb12]:
- File
src/runtime/autorelease.m
— part of check-in
[e7f4f80e23]
at
2020-01-24 03:03:32
on branch trunk
— runtime: Correctly handle AR pool push during pop
Getting a pointer and increasing it until we reach the top pointer does
not work: Releasing an object can temporarily create new autorelease
pools, which can trigger resizing of "objects" using realloc, which can
move it to a different address, which will then lead to continuing to
iterate on a now invalid pointer.This is now solved by using an index into "objects" instead. Since we're
now indexing for the pop, let's use indexes everywhere, as they're more
readable anyway.While debugging this, I noticed that the last pool is popped quite
frequently, only for a new pool to be pushed immediately again. This
resulted in a free followed by a malloc every time. Instead, keep the
pool, but let OFThread explicitly say when to free everything. (user: js, size: 3222) [annotate] [blame] [check-ins using] [more...]
︙ | ︙ | |||
25 26 27 28 29 30 31 | #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) # import "tlskey.h" #endif #if defined(OF_HAVE_COMPILER_TLS) static thread_local id *objects = NULL; | | | | | | | | < < < | | < > > > | > | > | | > | > > > > > | > | < > | > > > > | < < > | > | | | < | < < < < < < < < < < < | > | | < | < | < | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) # import "tlskey.h" #endif #if defined(OF_HAVE_COMPILER_TLS) static thread_local id *objects = NULL; static thread_local uintptr_t count = 0; static thread_local uintptr_t size = 0; #elif defined(OF_HAVE_THREADS) static of_tlskey_t objectsKey, countKey, sizeKey; #else static id *objects = NULL; static uintptr_t count = 0; static uintptr_t size = 0; #endif #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) OF_CONSTRUCTOR() { OF_ENSURE(of_tlskey_new(&objectsKey)); OF_ENSURE(of_tlskey_new(&countKey)); OF_ENSURE(of_tlskey_new(&sizeKey)); } #endif void * objc_autoreleasePoolPush() { #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) uintptr_t count = (uintptr_t)of_tlskey_get(countKey); #endif return (void *)count; } void objc_autoreleasePoolPop(void *pool) { #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) id *objects = of_tlskey_get(objectsKey); uintptr_t count = (uintptr_t)of_tlskey_get(countKey); #endif uintptr_t idx = (uintptr_t)pool; bool freeMem = false; if (idx == (uintptr_t)-1) { idx++; freeMem = true; } for (uintptr_t i = idx; i < count; i++) { [objects[i] release]; #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) objects = of_tlskey_get(objectsKey); count = (uintptr_t)of_tlskey_get(countKey); #endif } count = idx; if (freeMem) { free(objects); objects = NULL; #if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS) size = 0; #else OF_ENSURE(of_tlskey_set(objectsKey, objects)); OF_ENSURE(of_tlskey_set(sizeKey, (void *)0)); #endif } #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) OF_ENSURE(of_tlskey_set(countKey, (void *)count)); #endif } id _objc_rootAutorelease(id object) { #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) id *objects = of_tlskey_get(objectsKey); uintptr_t count = (uintptr_t)of_tlskey_get(countKey); uintptr_t size = (uintptr_t)of_tlskey_get(sizeKey); #endif if (count >= size) { if (size == 0) size = 16; else size *= 2; OF_ENSURE((objects = realloc(objects, size * sizeof(id))) != NULL); #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) OF_ENSURE(of_tlskey_set(objectsKey, objects)); OF_ENSURE(of_tlskey_set(sizeKey, (void *)size)); #endif } objects[count++] = object; #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) OF_ENSURE(of_tlskey_set(countKey, (void *)count)); #endif return object; } |