ObjFW  Check-in [96f946d7ad]

Overview
Comment:Use unsigned long for bit sets

This should be more efficient on some architectures.

As a nice side effect, this is also what Linux does in some userspace
APIs, so after this change, these macros can be used for this as well
(and Linux interestingly does not provide similar macros in the
userspace headers).

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 96f946d7ad5a1f5a96b35578004bc1e50fa459afbf3169f4140dde2e6f4618f5
User & Date: js on 2024-05-09 10:21:24
Other Links: manifest | tags
Context
2024-05-11
18:02
configure: Check whether blx is available on ARM check-in: 4f3f90e5e7 user: js tags: trunk
2024-05-09
10:22
Merge trunk into branch "gamecontroller" check-in: c0a80a897d user: js tags: gamecontroller
10:21
Use unsigned long for bit sets check-in: 96f946d7ad user: js tags: trunk
2024-05-05
19:04
OFStdIOStream: Add special case for column 0 check-in: 1c2fe75e6e user: js tags: trunk
Changes

Modified src/OFBitSetCharacterSet.h from [9f3314050d] to [ba3d4f6a9d].

19
20
21
22
23
24
25
26

27
28
29
30
31
19
20
21
22
23
24
25

26
27
28
29
30
31







-
+






#import "OFCharacterSet.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFBitSetCharacterSet: OFCharacterSet
{
	unsigned char *_bitset;
	unsigned long *_bitSet;
	size_t _size;
}
@end

OF_ASSUME_NONNULL_END

Modified src/OFBitSetCharacterSet.m from [b1982608cc] to [9db9ebbd67].

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
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







-
+






-
-
+
+

-
-
+
+
+
+




-
+













-
+






-
+


-
+


		void *pool = objc_autoreleasePoolPush();
		const OFUnichar *characters = string.characters;
		size_t length = string.length;

		for (size_t i = 0; i < length; i++) {
			OFUnichar c = characters[i];

			if (c / CHAR_BIT >= _size) {
			if (c / OF_ULONG_BIT >= _size) {
				size_t newSize;

				if (UINT32_MAX - c < 1)
					@throw [OFOutOfRangeException
					    exception];

				newSize = OFRoundUpToPowerOf2(CHAR_BIT, c + 1) /
				    CHAR_BIT;
				newSize = OFRoundUpToPowerOf2(OF_ULONG_BIT,
				    c + 1) / OF_ULONG_BIT;

				_bitset = OFResizeMemory(_bitset, newSize, 1);
				memset(_bitset + _size, '\0', newSize - _size);
				_bitSet = OFResizeMemory(_bitSet, newSize,
				    sizeof(unsigned long));
				memset(_bitSet + _size, '\0',
				    (newSize - _size) * sizeof(unsigned long));

				_size = newSize;
			}

			OFBitsetSet(_bitset, c);
			OFBitSetSet(_bitSet, c);
		}

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	OFFreeMemory(_bitset);
	OFFreeMemory(_bitSet);

	[super dealloc];
}

- (bool)characterIsMember: (OFUnichar)character
{
	if (character / CHAR_BIT >= _size)
	if (character / OF_ULONG_BIT >= _size)
		return false;

	return OFBitsetIsSet(_bitset, character);
	return OFBitSetIsSet(_bitSet, character);
}
@end

Modified src/OFSecureData.m from [5df33e3bf5] to [d0c4634748].

40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54







-
+







#import "OFOutOfRangeException.h"

#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON)
static const size_t chunkSize = 16;

struct Page {
	struct Page *next, *previous;
	void *map;
	unsigned long *map;
	unsigned char *page;
};

# if defined(OF_HAVE_COMPILER_TLS)
static thread_local struct Page *firstPage = NULL;
static thread_local struct Page *lastPage = NULL;
static thread_local struct Page **preallocatedPages = NULL;
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113
98
99
100
101
102
103
104


105
106
107
108
109
110
111
112
113







-
-
+
+







	munmap(pointer, numPages * pageSize);
}

static struct Page *
addPage(bool allowPreallocated)
{
	size_t pageSize = [OFSystemInfo pageSize];
	size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) /
	    CHAR_BIT;
	size_t mapSize = OFRoundUpToPowerOf2(OF_ULONG_BIT,
	    pageSize / chunkSize) / OF_ULONG_BIT;
	struct Page *page;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	struct Page *lastPage;
# endif

	if (allowPreallocated) {
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154







-
+








			return page;
		}
	}

	page = OFAllocMemory(1, sizeof(*page));
	@try {
		page->map = OFAllocZeroedMemory(1, mapSize);
		page->map = OFAllocZeroedMemory(mapSize, sizeof(unsigned long));
	} @catch (id e) {
		OFFreeMemory(page);
		@throw e;
	}
	@try {
		page->page = mapPages(1);
	} @catch (id e) {
182
183
184
185
186
187
188
189

190
191
192


193
194
195
196
197
198
199
182
183
184
185
186
187
188

189
190


191
192
193
194
195
196
197
198
199







-
+

-
-
+
+








	return page;
}

static void
removePageIfEmpty(struct Page *page)
{
	unsigned char *map = page->map;
	unsigned long *map = page->map;
	size_t pageSize = [OFSystemInfo pageSize];
	size_t mapSize = OFRoundUpToPowerOf2(CHAR_BIT, pageSize / chunkSize) /
	    CHAR_BIT;
	size_t mapSize = OFRoundUpToPowerOf2(OF_ULONG_BIT,
	    pageSize / chunkSize) / OF_ULONG_BIT;

	for (size_t i = 0; i < mapSize; i++)
		if (map[i] != 0)
			return;

	unmapPages(page->page, 1);
	OFFreeMemory(page->map);
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271







-
+











-
+



















-
+








	bytes = OFRoundUpToPowerOf2(chunkSize, bytes);
	chunks = chunksLeft = bytes / chunkSize;
	firstChunk = 0;
	pageSize = [OFSystemInfo pageSize];

	for (i = 0; i < pageSize / chunkSize; i++) {
		if (OFBitsetIsSet(page->map, i)) {
		if (OFBitSetIsSet(page->map, i)) {
			chunksLeft = chunks;
			firstChunk = i + 1;
			continue;
		}

		if (--chunksLeft == 0)
			break;
	}

	if (chunksLeft == 0) {
		for (size_t j = firstChunk; j < firstChunk + chunks; j++)
			OFBitsetSet(page->map, j);
			OFBitSetSet(page->map, j);

		return page->page + (chunkSize * firstChunk);
	}

	return NULL;
}

static void
freeMemory(struct Page *page, void *pointer, size_t bytes)
{
	size_t chunks, chunkIndex;

	bytes = OFRoundUpToPowerOf2(chunkSize, bytes);
	chunks = bytes / chunkSize;
	chunkIndex = ((uintptr_t)pointer - (uintptr_t)page->page) / chunkSize;

	OFZeroMemory(pointer, bytes);

	for (size_t i = 0; i < chunks; i++)
		OFBitsetClear(page->map, chunkIndex + i);
		OFBitSetClear(page->map, chunkIndex + i);
}
#endif

@implementation OFSecureData
@synthesize allowsSwappableMemory = _allowsSwappableMemory;

#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON) && \

Modified src/macros.h from [e71e68e9ff] to [3c8f4714cc].

936
937
938
939
940
941
942


943
944

945
946

947
948
949
950

951
952

953
954
955
956

957
958

959
960
961
962
963
964
965
936
937
938
939
940
941
942
943
944
945

946
947

948
949
950
951

952
953

954
955
956
957

958
959

960
961
962
963
964
965
966
967







+
+

-
+

-
+



-
+

-
+



-
+

-
+







 * @param pow2 The power of 2 to round up to
 * @param value The value to round up to the specified power of two
 * @return The specified value rounded up to the specified power of two
 */
#define OFRoundUpToPowerOf2(pow2, value)	\
    (((value) + (pow2) - 1) & ~((pow2) - 1))

#define OF_ULONG_BIT (sizeof(unsigned long) * CHAR_BIT)

static OF_INLINE bool
OFBitsetIsSet(unsigned char *_Nonnull storage, size_t idx)
OFBitSetIsSet(unsigned long *_Nonnull storage, size_t idx)
{
	return storage[idx / CHAR_BIT] & (1u << (idx % CHAR_BIT));
	return storage[idx / OF_ULONG_BIT] & (1ul << (idx % OF_ULONG_BIT));
}

static OF_INLINE void
OFBitsetSet(unsigned char *_Nonnull storage, size_t idx)
OFBitSetSet(unsigned long *_Nonnull storage, size_t idx)
{
	storage[idx / CHAR_BIT] |= (1u << (idx % CHAR_BIT));
	storage[idx / OF_ULONG_BIT] |= (1ul << (idx % OF_ULONG_BIT));
}

static OF_INLINE void
OFBitsetClear(unsigned char *_Nonnull storage, size_t idx)
OFBitSetClear(unsigned long *_Nonnull storage, size_t idx)
{
	storage[idx / CHAR_BIT] &= ~(1u << (idx % CHAR_BIT));
	storage[idx / OF_ULONG_BIT] &= ~(1ul << (idx % OF_ULONG_BIT));
}

static OF_INLINE void
OFZeroMemory(void *_Nonnull buffer_, size_t length)
{
	volatile unsigned char *buffer = (volatile unsigned char *)buffer_;