ObjFW  Check-in [0c7760bd05]

Overview
Comment:Don't use OFEnsure() in runtime
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0c7760bd052deda8311214f2b1cae0753c30830fa5e6a8048febe93100771e99
User & Date: js on 2021-05-02 14:28:59
Other Links: manifest | tags
Context
2021-05-02
14:43
Set library major version to 1 check-in: bae2619cf0 user: js tags: trunk
14:28
Don't use OFEnsure() in runtime check-in: 0c7760bd05 user: js tags: trunk
11:59
ofhttp: Fix typo check-in: 5a087b5409 user: js tags: trunk
Changes

Modified src/runtime/autorelease.m from [2b09f19f70] to [c90ec8958a].

47
48
49
50
51
52
53
54

55
56


57
58
59
60
61
62
63
47
48
49
50
51
52
53

54


55
56
57
58
59
60
61
62
63







-
+
-
-
+
+







static uintptr_t count = 0;
static uintptr_t size = 0;
#endif

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
OF_CONSTRUCTOR()
{
	OFEnsure(OFTLSKeyNew(&objectsKey) == 0);
	if (OFTLSKeyNew(&objectsKey) != 0 || OFTLSKeyNew(&countKey) != 0 ||
	OFEnsure(OFTLSKeyNew(&countKey) == 0);
	OFEnsure(OFTLSKeyNew(&sizeKey) == 0);
	    OFTLSKeyNew(&sizeKey) != 0)
		OBJC_ERROR("Failed to create TLS keys!");
}
#endif

void *
objc_autoreleasePoolPush()
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
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
134
135
136
137
138


139
140
141
142
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
134
135
136
137
138
139
140

141
142
143
144
145
146







-
-
+
+
+




-
+
+


















-
-
+
+


-
-
+
+
+






-
+
+





	if (freeMem) {
		free(objects);
		objects = NULL;
#if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS)
		size = 0;
#else
		OFEnsure(OFTLSKeySet(objectsKey, objects) == 0);
		OFEnsure(OFTLSKeySet(sizeKey, (void *)0) == 0);
		if (OFTLSKeySet(objectsKey, objects) != 0 ||
		    OFTLSKeySet(sizeKey, (void *)0) != 0)
			OBJC_ERROR("Failed to set TLS key!");
#endif
	}

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OFEnsure(OFTLSKeySet(countKey, (void *)count) == 0);
	if (OFTLSKeySet(countKey, (void *)count) != 0)
		OBJC_ERROR("Failed to set TLS key!");
#endif
}

id
_objc_rootAutorelease(id object)
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	id *objects = OFTLSKeyGet(objectsKey);
	uintptr_t count = (uintptr_t)OFTLSKeyGet(countKey);
	uintptr_t size = (uintptr_t)OFTLSKeyGet(sizeKey);
#endif

	if (count >= size) {
		if (size == 0)
			size = 16;
		else
			size *= 2;

		OFEnsure((objects =
		    realloc(objects, size * sizeof(id))) != NULL);
		if ((objects = realloc(objects, size * sizeof(id))) == NULL)
			OBJC_ERROR("Failed to resize autorelease pool!");

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
		OFEnsure(OFTLSKeySet(objectsKey, objects) == 0);
		OFEnsure(OFTLSKeySet(sizeKey, (void *)size) == 0);
		if (OFTLSKeySet(objectsKey, objects) != 0 ||
		    OFTLSKeySet(sizeKey, (void *)size) != 0)
			OBJC_ERROR("Failed to set TLS key!");
#endif
	}

	objects[count++] = object;

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OFEnsure(OFTLSKeySet(countKey, (void *)count) == 0);
	if (OFTLSKeySet(countKey, (void *)count) != 0)
		OBJC_ERROR("Failed to set TLS key!");
#endif

	return object;
}

Modified src/runtime/class.m from [70c18ee4cd] to [8556b52111].

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490







491
492
493
494
495
496
497
470
471
472
473
474
475
476



477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500







-
-
-










-
+
+
+
+
+
+
+








Class
objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
{
	struct objc_class *class, *metaclass;
	Class iter, rootclass = Nil;

	if (extraBytes > LONG_MAX)
		OBJC_ERROR("extraBytes out of range!");

	if ((class = calloc(1, sizeof(*class))) == NULL ||
	    (metaclass = calloc(1, sizeof(*class))) == NULL)
		OBJC_ERROR("Not enough memory to allocate class pair for class "
		    "%s!", name);

	class->isa = metaclass;
	class->superclass = superclass;
	class->name = name;
	class->info = OBJC_CLASS_INFO_CLASS;
	class->instanceSize = (superclass != Nil ?
	    superclass->instanceSize : 0) + (long)extraBytes;
	    superclass->instanceSize : 0);

	if (extraBytes > LONG_MAX ||
	    LONG_MAX - class->instanceSize < (long)extraBytes)
		OBJC_ERROR("extraBytes too large!");

	class->instanceSize += (long)extraBytes;

	for (iter = superclass; iter != Nil; iter = iter->superclass)
		rootclass = iter;

	metaclass->isa = (rootclass != Nil ? rootclass->isa : class);
	metaclass->superclass = (superclass != Nil ? superclass->isa : Nil);
	metaclass->name = name;
627
628
629
630
631
632
633
634


635
636
637
638
639
640
641
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645







-
+
+








	objc_globalMutex_lock();

	if ((ret = malloc((classesCount + 1) * sizeof(Class))) == NULL)
		OBJC_ERROR("Failed to allocate memory for class list!");

	count = objc_getClassList(ret, classesCount);
	OFEnsure(count == classesCount);
	if (count != classesCount)
		OBJC_ERROR("Fatal internal inconsistency!");

	ret[count] = Nil;

	if (length != NULL)
		*length = count;

	objc_globalMutex_unlock();
976
977
978
979
980
981
982
983


984
985
986
987
988
989
990
991
992
993
994
995
980
981
982
983
984
985
986

987
988
989
990
991
992
993
994
995
996
997
998
999
1000







-
+
+












			 * UINT32_MAX so that it will get increased at the end
			 * of the loop and thus become 0.
			 */
			i = UINT32_MAX;
		}
	}

	OFEnsure(classesCount == 0);
	if (classesCount != 0)
		OBJC_ERROR("Fatal internal inconsistency!");

	if (emptyDTable != NULL) {
		objc_dtable_free(emptyDTable);
		emptyDTable = NULL;
	}

	objc_sparsearray_free(fastPath);
	fastPath = NULL;

	objc_hashtable_free(classes);
	classes = NULL;
}

Modified src/runtime/exception.m from [cb2a5e9390] to [b58329f870].

249
250
251
252
253
254
255
256

257
258
259
260
261
262
263
249
250
251
252
253
254
255

256
257
258
259
260
261
262
263







-
+







static struct objc_exception emergencyExceptions[numEmergencyExceptions];
#ifdef OF_HAVE_THREADS
static OFSpinlock emergencyExceptionsSpinlock;

OF_CONSTRUCTOR()
{
	if (OFSpinlockNew(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot create spinlock!");
		OBJC_ERROR("Failed to create spinlock!");
}
#endif

static uint64_t
readULEB128(const uint8_t **ptr)
{
	uint64_t value = 0;
714
715
716
717
718
719
720
721

722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738
739
740
741

742
743
744
745
746
747
748
749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
714
715
716
717
718
719
720

721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
737
738
739
740

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755

756
757
758
759
760
761
762
763







-
+






-
+












-
+














-
+








static void
emergencyExceptionCleanup(_Unwind_Reason_Code reason,
    struct _Unwind_Exception *ex)
{
#ifdef OF_HAVE_THREADS
	if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot lock spinlock!");
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	ex->class = 0;

#ifdef OF_HAVE_THREADS
	if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot unlock spinlock!");
		OBJC_ERROR("Failed to unlock spinlock!");
#endif
}

void
objc_exception_throw(id object)
{
	struct objc_exception *e = calloc(1, sizeof(*e));
	bool emergency = false;

	if (e == NULL) {
#ifdef OF_HAVE_THREADS
		if (OFSpinlockLock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Cannot lock spinlock!");
			OBJC_ERROR("Failed to lock spinlock!");
#endif

		for (uint_fast8_t i = 0; i < numEmergencyExceptions; i++) {
			if (emergencyExceptions[i].exception.class == 0) {
				e = &emergencyExceptions[i];
				e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
				emergency = true;

				break;
			}
		}

#ifdef OF_HAVE_THREADS
		if (OFSpinlockUnlock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Cannot lock spinlock!");
			OBJC_ERROR("Failed to lock spinlock!");
#endif
	}

	if (e == NULL)
		OBJC_ERROR("Not enough memory to allocate exception!");

	e->exception.class = GNUCOBJC_EXCEPTION_CLASS;

Modified src/runtime/hashtable.m from [91acb00f82] to [ad954a7a5c].

115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129







-
+







				last = table->data[i]->hash & (newSize - 1);

				for (j = 0; j < last && newData[j] != NULL;
				    j++);
			}

			if (j >= last)
				OBJC_ERROR("No free bucket!");
				OBJC_ERROR("No free bucket in hash table!");

			newData[j] = table->data[i];
		}
	}

	free(table->data);
	table->data = newData;
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201







-
+







		last = hash & (table->size - 1);

		for (i = 0; i < last && table->data[i] != NULL &&
		    table->data[i] != &objc_deletedBucket; i++);
	}

	if (i >= last)
		OBJC_ERROR("No free bucket!");
		OBJC_ERROR("No free bucket in hash table!");

	if ((bucket = malloc(sizeof(*bucket))) == NULL)
		OBJC_ERROR("Not enough memory to allocate hash table bucket!");

	bucket->key = key;
	bucket->hash = hash;
	bucket->object = object;

Modified src/runtime/ivar.m from [22d1127488] to [5caeed37fa].

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







-
+







			*outCount = 0;

		objc_globalMutex_unlock();
		return NULL;
	}

	if ((ivars = malloc((count + 1) * sizeof(Ivar))) == NULL)
		OBJC_ERROR("Not enough memory to copy ivars");
		OBJC_ERROR("Not enough memory to copy ivars!");

	for (unsigned int i = 0; i < count; i++)
		ivars[i] = &class->ivars->ivars[i];
	ivars[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

Modified src/runtime/lookup.m from [d4c41afde5] to [7e08e68b8b].

40
41
42
43
44
45
46
47
48



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


47
48
49
50
51
52
53
54
55
56







-
-
+
+
+







	if (!(object_getClass(object)->info & OBJC_CLASS_INFO_INITIALIZED)) {
		Class class = (isClass
		    ? (Class)object : object_getClass(object));

		objc_initializeClass(class);

		if (!(class->info & OBJC_CLASS_INFO_SETUP))
			OBJC_ERROR("Could not dispatch message for incomplete "
			    "class %s!", class_getName(class));
			OBJC_ERROR("Could not dispatch message %s for "
			    "incomplete class %s!",
			    sel_getName(selector), class_getName(class));

		/*
		 * We don't need to handle the case that super was called.
		 * The reason for this is that a call to super is not possible
		 * before a message to the class has been sent and it thus has
		 * been initialized together with its superclasses.
		 */

Modified src/runtime/method.m from [f36033e5e6] to [4ccd14f099].

49
50
51
52
53
54
55

56



57
58
59
60
61
62
63
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66







+
-
+
+
+







	if ((methods = malloc((count + 1) * sizeof(Method))) == NULL)
		OBJC_ERROR("Not enough memory to copy methods");

	i = 0;
	for (iter = class->methodList; iter != NULL; iter = iter->next)
		for (unsigned int j = 0; j < iter->count; j++)
			methods[i++] = &iter->methods[j];

	OFEnsure(i == count);
	if (i != count)
		OBJC_ERROR("Fatal internal inconsistency!");

	methods[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_globalMutex_unlock();

Modified src/runtime/property.m from [4164734943] to [6e20bc37ae].

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







-
+











-
+
+



-
+
+


















-
+
+


















-
+
+







#endif

#ifdef OF_HAVE_THREADS
OF_CONSTRUCTOR()
{
	for (size_t i = 0; i < numSpinlocks; i++)
		if (OFSpinlockNew(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to initialize spinlocks!");
			OBJC_ERROR("Failed to create spinlocks!");
}
#endif

id
objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(ptr);

		OFEnsure(OFSpinlockLock(&spinlocks[slot]) == 0);
		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
		@try {
			return [[*ptr retain] autorelease];
		} @finally {
			OFEnsure(OFSpinlockUnlock(&spinlocks[slot]) == 0);
			if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
				OBJC_ERROR("Failed to unlock spinlock!");
		}
#else
		return [[*ptr retain] autorelease];
#endif
	}

	return *(id *)(void *)((char *)self + offset);
}

void
objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, bool atomic,
    signed char copy)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(ptr);

		OFEnsure(OFSpinlockLock(&spinlocks[slot]) == 0);
		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
		@try {
#endif
			id old = *ptr;

			switch (copy) {
			case 0:
				*ptr = [value retain];
				break;
			case 2:
				*ptr = [value mutableCopy];
				break;
			default:
				*ptr = [value copy];
			}

			[old release];
#ifdef OF_HAVE_THREADS
		} @finally {
			OFEnsure(OFSpinlockUnlock(&spinlocks[slot]) == 0);
			if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
				OBJC_ERROR("Failed to unlock spinlock!");
		}
#endif

		return;
	}

	id *ptr = (id *)(void *)((char *)self + offset);
120
121
122
123
124
125
126
127


128
129
130
131


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148


149
150
151
152


153
154
155
156
157
158
159
124
125
126
127
128
129
130

131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158

159
160
161
162
163
164
165
166
167







-
+
+



-
+
+
















-
+
+



-
+
+







objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(src);

		OFEnsure(OFSpinlockLock(&spinlocks[slot]) == 0);
		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		OFEnsure(OFSpinlockUnlock(&spinlocks[slot]) == 0);
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
#endif

		return;
	}

	memcpy(dest, src, size);
}

void
objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		size_t slot = spinlockSlot(src);

		OFEnsure(OFSpinlockLock(&spinlocks[slot]) == 0);
		if (OFSpinlockLock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to lock spinlock!");
#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		OFEnsure(OFSpinlockUnlock(&spinlocks[slot]) == 0);
		if (OFSpinlockUnlock(&spinlocks[slot]) != 0)
			OBJC_ERROR("Failed to unlock spinlock!");
#endif

		return;
	}

	memcpy(dest, src, size);
}
192
193
194
195
196
197
198

199



200
201
202
203
204
205
206
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
215
216
217







+
-
+
+
+







	if (properties == NULL)
		OBJC_ERROR("Not enough memory to copy properties");

	i = 0;
	for (iter = class->propertyList; iter != NULL; iter = iter->next)
		for (unsigned int j = 0; j < iter->count; j++)
			properties[i++] = &iter->properties[j];

	OFEnsure(i == count);
	if (i != count)
		OBJC_ERROR("Fatal internal inconsistency!");

	properties[count] = NULL;

	if (outCount != NULL)
		*outCount = count;

	objc_globalMutex_unlock();

254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271

272
273
274
275







-
+



	BOOL_CASE('D', extendedAttributes, OBJC_PROPERTY_DYNAMIC)
	BOOL_CASE('W', extendedAttributes, OBJC_PROPERTY_WEAK)
#undef BOOL_CASE
	}

	if (nullIsError && ret == NULL)
		OBJC_ERROR("Not enough memory to copy property attribute "
		    "value");
		    "value!");

	return ret;
}

Modified src/runtime/selector.m from [5e713d47e2] to [595eb87101].

76
77
78
79
80
81
82
83

84
85
86

87
88
89
90
91
92
93
76
77
78
79
80
81
82

83



84
85
86
87
88
89
90
91







-
+
-
-
-
+








	if (selectors != NULL &&
	    (selector = objc_hashtable_get(selectors, name)) != NULL) {
		objc_globalMutex_unlock();
		return (SEL)selector;
	}

	if ((selector = malloc(sizeof(*selector))) == NULL)
	if ((selector = malloc(sizeof(*selector))) == NULL ||
		OBJC_ERROR("Not enough memory to allocate selector!");

	if ((selector->UID = (uintptr_t)objc_strdup(name)) == 0)
	    (selector->UID = (uintptr_t)objc_strdup(name)) == 0)
		OBJC_ERROR("Not enough memory to allocate selector!");

	selector->typeEncoding = NULL;

	if ((freeList = realloc(freeList,
	    sizeof(void *) * (freeListCount + 2))) == NULL)
		OBJC_ERROR("Not enough memory to allocate selector!");

Modified src/runtime/sparsearray.m from [ac31f7403e] to [0600278cf2].

22
23
24
25
26
27
28
29

30
31
32

33
34
35
36
37
38
39
22
23
24
25
26
27
28

29



30
31
32
33
34
35
36
37







-
+
-
-
-
+







#import "private.h"

struct objc_sparsearray *
objc_sparsearray_new(uint8_t levels)
{
	struct objc_sparsearray *sparsearray;

	if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL)
	if ((sparsearray = calloc(1, sizeof(*sparsearray))) == NULL ||
		OBJC_ERROR("Failed to allocate memory for sparse array!");

	if ((sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL)
	    (sparsearray->data = calloc(1, sizeof(*sparsearray->data))) == NULL)
		OBJC_ERROR("Failed to allocate memory for sparse array!");

	sparsearray->levels = levels;

	return sparsearray;
}

Modified src/runtime/synchronized.m from [0c53071c1e] to [4edf9604c8].

126
127
128
129
130
131
132
133

134
135
136
137
126
127
128
129
130
131
132

133
134
135
136
137







-
+





		if (OFPlainMutexUnlock(&mutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		return 0;
	}

	OBJC_ERROR("objc_sync_exit() was called for an object not locked!");
	OBJC_ERROR("objc_sync_exit() was called for an unlocked object!");
#else
	return 0;
#endif
}