From 4f4a488762705769be6a608ffb4830567dfa6795 Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Sun, 26 Jul 2009 15:28:41 -0700 Subject: [PATCH 1/4] Remove debugger command in CPPopUpButton that breaks Release builds. Reviewed by me. --- AppKit/CPPopUpButton.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPPopUpButton.j b/AppKit/CPPopUpButton.j index 47d7e2176..526a1cb4d 100644 --- a/AppKit/CPPopUpButton.j +++ b/AppKit/CPPopUpButton.j @@ -550,7 +550,7 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down"); - (void)synchronizeTitleAndSelectedItem { var item = nil; -debugger; + if ([self pullsDown]) { var items = [_menu itemArray]; From 5ce96b45bb8ca28f3424bf8ddfb06d8745e08af1 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 26 Jul 2009 22:46:22 -0700 Subject: [PATCH 2/4] Slight performance improvement and memory improvement by moving the storage of KVO proxy objects. --- Foundation/CPKeyValueObserving.j | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/Foundation/CPKeyValueObserving.j b/Foundation/CPKeyValueObserving.j index 7a1d575ae..5c57449a2 100644 --- a/Foundation/CPKeyValueObserving.j +++ b/Foundation/CPKeyValueObserving.j @@ -58,7 +58,7 @@ if (!anObserver || !aPath) return; - [[KVOProxyMap objectForKey:[self UID]] _removeObserver:anObserver forKeyPath:aPath]; + [self[KVOProxyKey] _removeObserver:anObserver forKeyPath:aPath]; } + (BOOL)automaticallyNotifiesObserversForKey:(CPString)aKey @@ -98,12 +98,9 @@ CPKeyValueChangeInsertion = 2; CPKeyValueChangeRemoval = 3; CPKeyValueChangeReplacement = 4; -//convenience -var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld; - -// Map of real objects to their KVO proxy -var KVOProxyMap = [CPDictionary dictionary], - DependentKeysMap = [CPDictionary dictionary]; +var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, + DependentKeysMap = [CPDictionary dictionary], + KVOProxyKey = "$KVOPROXY"; //rule of thumb: _ methods are called on the real proxy object, others are called on the "fake" proxy object (aka the real object) @@ -119,7 +116,7 @@ var KVOProxyMap = [CPDictionary dictionary], + (id)proxyForObject:(CPObject)anObject { - var proxy = [KVOProxyMap objectForKey:[anObject UID]]; + var proxy = anObject[KVOProxyKey]; if (proxy) return proxy; @@ -128,7 +125,7 @@ var KVOProxyMap = [CPDictionary dictionary], [proxy _replaceClass]; - [KVOProxyMap setObject:proxy forKey:[anObject UID]]; + anObject[KVOProxyKey] = proxy; return proxy; } @@ -205,9 +202,10 @@ var KVOProxyMap = [CPDictionary dictionary], } } - var affectingKeys = [[_nativeClass keyPathsForValuesAffectingValueForKey:aKey] allObjects]; + var affectingKeys = [[_nativeClass keyPathsForValuesAffectingValueForKey:aKey] allObjects], + affectingKeysCount = affectingKeys ? affectingKeys.length : 0; - if (![affectingKeys count]) + if (!affectingKeysCount) return; var dependentKeysForClass = [DependentKeysMap objectForKey:[_nativeClass UID]]; @@ -218,11 +216,9 @@ var KVOProxyMap = [CPDictionary dictionary], [DependentKeysMap setObject:dependentKeysForClass forKey:[_nativeClass UID]]; } - var count = [affectingKeys count]; - - while (count--) + while (affectingKeysCount--) { - var affectingKey = affectingKeys[count], + var affectingKey = affectingKeys[affectingKeysCount], affectedKeys = [dependentKeysForClass objectForKey:affectingKey]; if (!affectedKeys) @@ -288,7 +284,7 @@ var KVOProxyMap = [CPDictionary dictionary], if (![_observersForKey count]) { _targetObject.isa = _nativeClass; //restore the original class - [KVOProxyMap removeObjectForKey:[_targetObject UID]]; + delete _targetObject[KVOProxyKey]; } } @@ -360,7 +356,7 @@ var KVOProxyMap = [CPDictionary dictionary], } var observers = [[_observersForKey objectForKey:aKey] allValues], - count = [observers count]; + count = observers ? observers.length : 0; while (count--) { @@ -425,7 +421,7 @@ var KVOProxyMap = [CPDictionary dictionary], - (Class)class { - return [KVOProxyMap objectForKey:[self UID]]._nativeClass; + return self[KVOProxyKey]._nativeClass; } - (Class)superclass From 43706041658e36ef8338c0c0bf515bad1c7d0bba Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 26 Jul 2009 23:40:52 -0700 Subject: [PATCH 3/4] Remove several CPDictionaries in favor of Objects, about a 15% performance gain. --- Foundation/CPKeyValueObserving.j | 47 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/Foundation/CPKeyValueObserving.j b/Foundation/CPKeyValueObserving.j index 5c57449a2..897702537 100644 --- a/Foundation/CPKeyValueObserving.j +++ b/Foundation/CPKeyValueObserving.j @@ -99,7 +99,7 @@ CPKeyValueChangeRemoval = 3; CPKeyValueChangeReplacement = 4; var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, - DependentKeysMap = [CPDictionary dictionary], + DependentKeysMap = {}, KVOProxyKey = "$KVOPROXY"; //rule of thumb: _ methods are called on the real proxy object, others are called on the "fake" proxy object (aka the real object) @@ -110,7 +110,8 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, id _targetObject; Class _nativeClass; CPDictionary _changesForKey; - CPDictionary _observersForKey; + Object _observersForKey; + int _observersForKeyLength; CPSet _replacedKeys; } @@ -136,9 +137,10 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, _targetObject = aTarget; _nativeClass = [aTarget class]; - _observersForKey = [CPDictionary dictionary]; - _changesForKey = [CPDictionary dictionary]; _replacedKeys = [CPSet set]; + _observersForKey = {}; + _changesForKey = {}; + _observersForKeyLength = 0; return self; } @@ -208,23 +210,23 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, if (!affectingKeysCount) return; - var dependentKeysForClass = [DependentKeysMap objectForKey:[_nativeClass UID]]; + var dependentKeysForClass = DependentKeysMap[[_nativeClass UID]]; if (!dependentKeysForClass) { - dependentKeysForClass = [CPDictionary new]; - [DependentKeysMap setObject:dependentKeysForClass forKey:[_nativeClass UID]]; + dependentKeysForClass = {}; + DependentKeysMap[[_nativeClass UID]] = dependentKeysForClass; } while (affectingKeysCount--) { var affectingKey = affectingKeys[affectingKeysCount], - affectedKeys = [dependentKeysForClass objectForKey:affectingKey]; + affectedKeys = dependentKeysForClass[affectingKey]; if (!affectedKeys) { affectedKeys = [CPSet new]; - [dependentKeysForClass setObject:affectedKeys forKey:affectingKey]; + dependentKeysForClass[affectingKey] = affectedKeys; } [affectedKeys addObject:aKey]; @@ -244,12 +246,13 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, else [self _replaceSetterForKey:aPath]; - var observers = [_observersForKey objectForKey:aPath]; + var observers = _observersForKey[aPath]; if (!observers) { observers = [CPDictionary dictionary]; - [_observersForKey setObject:observers forKey:aPath]; + _observersForKey[aPath] = observers; + _observersForKeyLength++; } [observers setObject:_CPKVOInfoMake(anObserver, options, aContext, forwarder) forKey:[anObserver UID]]; @@ -268,7 +271,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, - (void)_removeObserver:(id)anObserver forKeyPath:(CPString)aPath { - var observers = [_observersForKey objectForKey:aPath]; + var observers = _observersForKey[aPath]; if (aPath.indexOf('.') != CPNotFound) { @@ -279,9 +282,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, [observers removeObjectForKey:[anObserver UID]]; if (![observers count]) - [_observersForKey removeObjectForKey:aPath]; + { + _observersForKeyLength--; + delete _observersForKey[aPath]; + } - if (![_observersForKey count]) + if (!_observersForKeyLength) { _targetObject.isa = _nativeClass; //restore the original class delete _targetObject[KVOProxyKey]; @@ -292,7 +298,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, - (void)_sendNotificationsForKey:(CPString)aKey changeOptions:(CPDictionary)changeOptions isBefore:(BOOL)isBefore { - var changes = [_changesForKey objectForKey:aKey]; + var changes = _changesForKey[aKey]; if (isBefore) { @@ -324,7 +330,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, [changes setObject:1 forKey:CPKeyValueChangeNotificationIsPriorKey]; - [_changesForKey setObject:changes forKey:aKey]; + _changesForKey[aKey] = changes; } else { @@ -355,7 +361,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, } } - var observers = [[_observersForKey objectForKey:aKey] allValues], + var observers = [_observersForKey[aKey] allValues], count = observers ? observers.length : 0; while (count--) @@ -368,7 +374,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, [observerInfo.observer observeValueForKeyPath:aKey ofObject:_targetObject change:changes context:observerInfo.context]; } - var keysComposedOfKey = [[[DependentKeysMap objectForKey:[_nativeClass UID]] objectForKey:aKey] allObjects]; + var dependentKeysMap = DependentKeysMap[[_nativeClass UID]]; + + if (!dependentKeysMap) + return; + + var keysComposedOfKey = [dependentKeysMap[aKey] allObjects]; if (!keysComposedOfKey) return; From 0ef4e9bca5901602b9edc7519c54b48eccea3049 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 26 Jul 2009 23:56:18 -0700 Subject: [PATCH 4/4] store dependent keys on the class object itself, rather than in a global map. --- Foundation/CPKeyValueObserving.j | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Foundation/CPKeyValueObserving.j b/Foundation/CPKeyValueObserving.j index 897702537..a2c3fc2d5 100644 --- a/Foundation/CPKeyValueObserving.j +++ b/Foundation/CPKeyValueObserving.j @@ -99,7 +99,7 @@ CPKeyValueChangeRemoval = 3; CPKeyValueChangeReplacement = 4; var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, - DependentKeysMap = {}, + DependentKeysKey = "$KVODEPENDENT", KVOProxyKey = "$KVOPROXY"; //rule of thumb: _ methods are called on the real proxy object, others are called on the "fake" proxy object (aka the real object) @@ -210,12 +210,12 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, if (!affectingKeysCount) return; - var dependentKeysForClass = DependentKeysMap[[_nativeClass UID]]; + var dependentKeysForClass = _nativeClass[DependentKeysKey]; if (!dependentKeysForClass) { dependentKeysForClass = {}; - DependentKeysMap[[_nativeClass UID]] = dependentKeysForClass; + _nativeClass[DependentKeysKey] = dependentKeysForClass; } while (affectingKeysCount--) @@ -374,7 +374,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, [observerInfo.observer observeValueForKeyPath:aKey ofObject:_targetObject change:changes context:observerInfo.context]; } - var dependentKeysMap = DependentKeysMap[[_nativeClass UID]]; + var dependentKeysMap = _nativeClass[DependentKeysKey]; if (!dependentKeysMap) return;