Skip to content

Commit

Permalink
Merge branch 'kvc-caching' into kvo-kvc-test
Browse files Browse the repository at this point in the history
  • Loading branch information
hmelder committed Sep 10, 2024
2 parents 8a5c2b4 + e7b18c1 commit c06a466
Show file tree
Hide file tree
Showing 34 changed files with 1,409 additions and 18 deletions.
12 changes: 6 additions & 6 deletions Headers/Foundation/NSGeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ extern "C" {
CGFloat y;
}</example>
<p>Represents a 2-d cartesian position.</p> */
typedef struct _NSPoint NSPoint;
struct _NSPoint
typedef struct CGPoint NSPoint;
struct CGPoint
{
CGFloat x;
CGFloat y;
Expand All @@ -76,8 +76,8 @@ typedef NSPoint *NSPointPointer;
CGFloat height;
}</example>
<p>Floating point rectangle size.</p> */
typedef struct _NSSize NSSize;
struct _NSSize
typedef struct CGSize NSSize;
struct CGSize
{
CGFloat width;
CGFloat height;
Expand All @@ -97,8 +97,8 @@ typedef NSSize *NSSizePointer;
}</example>
<p>Rectangle.</p> */
typedef struct _NSRect NSRect;
struct _NSRect
typedef struct CGRect NSRect;
struct CGRect
{
NSPoint origin;
NSSize size;
Expand Down
11 changes: 7 additions & 4 deletions Source/Additions/GSObjCRuntime.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

#import "../GSPrivate.h"
#import "../GSPThread.h"
#import "../typeEncodingHelper.h"

#include <objc/Protocol.h>

Expand Down Expand Up @@ -1317,7 +1318,8 @@ unsigned long long (*imp)(id, SEL) =
break;

case _C_STRUCT_B:
if (GSSelectorTypesMatch(@encode(NSPoint), type))
{
if (IS_CGPOINT_ENCODING(type))
{
NSPoint v;

Expand All @@ -1334,7 +1336,7 @@ unsigned long long (*imp)(id, SEL) =
}
val = [NSValue valueWithPoint: v];
}
else if (GSSelectorTypesMatch(@encode(NSRange), type))
else if (IS_NSRANGE_ENCODING(type))
{
NSRange v;

Expand All @@ -1351,7 +1353,7 @@ unsigned long long (*imp)(id, SEL) =
}
val = [NSValue valueWithRange: v];
}
else if (GSSelectorTypesMatch(@encode(NSRect), type))
else if (IS_CGRECT_ENCODING(type))
{
NSRect v;

Expand All @@ -1368,7 +1370,7 @@ unsigned long long (*imp)(id, SEL) =
}
val = [NSValue valueWithRect: v];
}
else if (GSSelectorTypesMatch(@encode(NSSize), type))
else if (IS_CGSIZE_ENCODING(type))
{
NSSize v;

Expand Down Expand Up @@ -1410,6 +1412,7 @@ unsigned long long (*imp)(id, SEL) =
}
}
break;
}

default:
#ifdef __GNUSTEP_RUNTIME__
Expand Down
5 changes: 5 additions & 0 deletions Source/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,11 @@ else
endif


ifeq ($(OBJC_RUNTIME_LIB), ng)
BASE_MFILES += \
NSKeyValueCoding+Caching.m
endif

ifneq ($(GNUSTEP_TARGET_OS), mingw32)
ifneq ($(GNUSTEP_TARGET_OS), mingw64)
ifneq ($(GNUSTEP_TARGET_OS), windows)
Expand Down
55 changes: 55 additions & 0 deletions Source/NSKeyValueCoding+Caching.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** Key-Value Coding Safe Caching Support
Copyright (C) 2024 Free Software Foundation, Inc.
Written by: Hugo Melder <[email protected]>
Created: August 2024
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/

/**
* It turns out that valueForKey: is a very expensive operation, and a major
* bottleneck for Key-Value Observing and other operations such as sorting
* an array by key.
*
* The accessor search patterns for Key-Value observing are discussed in the
* Apple Key-Value Coding Programming Guide. The return value may be
* encapuslated into an NSNumber or NSValue object, depending on the Objective-C
* type encoding of the return value. This means that once valueForKey: found an
* existing accessor, the Objective-C type encoding of the accessor is
* retrieved. We then go through a huge switch case to determine the right way
* to invoke the IMP and potentially encapsulate the return type. The resulting
* object is then returned.
* The algorithm for setValue:ForKey: is similar.
*
* We can speed this up by caching the IMP of the accessor in a hash table.
* However, without proper versioning, this quickly becomes very dangerous.
* The user might exchange implementations, or add new ones expecting the
* search pattern invariant to still hold. If we clamp onto an IMP, this
* invariant no longer holds.
*
* We will make use of libobjc2's safe caching to avoid this.
*
* Note that the caching is opaque. You will only need to redirect all
* valueForKey: calls to the function below.
*/

#import "Foundation/NSString.h"

id
valueForKeyWithCaching(id obj, NSString *aKey);
Loading

0 comments on commit c06a466

Please sign in to comment.