From ec81778b56a48ce204033a9ca2e02a515c13a88d Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Fri, 17 Jan 2025 06:43:01 +0800 Subject: [PATCH 1/5] Revert "remove direct function calls to Obj-C methods" This reverts commit 19d6a0cfa9cc5a4aa6539c07ade6c62a3b60dd6b. --- NoodleLineNumberView.h | 10 ++++++++++ NoodleLineNumberView.m | 26 ++++++++++++++++++++------ RController.h | 4 ++++ RController.m | 31 ++++++++++++++++++++++--------- RScriptEditorGlyphGenerator.h | 3 +++ RScriptEditorGlyphGenerator.m | 16 ++++++++++++++++ RScriptEditorTextStorage.h | 7 +++++++ RScriptEditorTextStorage.m | 18 ++++++++++++------ RScriptEditorTypeSetter.h | 1 + RScriptEditorTypeSetter.m | 8 ++++++-- 10 files changed, 101 insertions(+), 23 deletions(-) diff --git NoodleLineNumberView.h NoodleLineNumberView.h index f0f3a0f..33773a2 100644 --- NoodleLineNumberView.h +++ NoodleLineNumberView.h @@ -74,6 +74,16 @@ static inline id NSArrayObjectAtIndex(NSArray *self, NSUInteger i) // Add support for selection by clicking/dragging NSUInteger dragSelectionStartLine; + SEL lineNumberForCharacterIndexSel; + IMP lineNumberForCharacterIndexIMP; + SEL lineRangeForRangeSel; + SEL numberWithUnsignedIntegerSel; + IMP numberWithUnsignedIntegerIMP; + SEL addObjectSel; + IMP addObjectIMP; + SEL rangeOfLineSel; + Class numberClass; + NSLayoutManager *layoutManager; NSTextContainer *container; NSTextView *clientView; diff --git NoodleLineNumberView.m NoodleLineNumberView.m index 308bed5..afe71a0 100644 --- NoodleLineNumberView.m +++ NoodleLineNumberView.m @@ -97,8 +97,18 @@ [self updateGutterThicknessConstants]; currentRuleThickness = 0.0f; + // Cache loop methods for speed + lineNumberForCharacterIndexSel = @selector(lineNumberForCharacterIndex:); + lineNumberForCharacterIndexIMP = [self methodForSelector:lineNumberForCharacterIndexSel]; + lineRangeForRangeSel = @selector(lineRangeForRange:); + addObjectSel = @selector(addObject:); + numberWithUnsignedIntegerSel = @selector(numberWithUnsignedInteger:); + numberWithUnsignedIntegerIMP = [NSNumber methodForSelector:numberWithUnsignedIntegerSel]; + rangeOfLineSel = @selector(getLineStart:end:contentsEnd:forRange:); + currentNumberOfLines = 1; lineWrapping = NO; + numberClass = [NSNumber class]; normalBackgroundColor = [[NSColor colorWithCalibratedWhite: 0.95 alpha: 1.0] retain]; foldedBackgroundColor = [[NSColor colorWithCalibratedWhite: 0.85 alpha: 1.0] retain]; @@ -282,7 +292,7 @@ // It doesn't show up in the glyphs so would not be accounted for. range.length++; - for (line = [self lineNumberForCharacterIndex: range.location]; line < count; line++) + for (line = (NSUInteger)(*lineNumberForCharacterIndexIMP)(self, lineNumberForCharacterIndexSel, range.location); line < count; line++) { rects = [layoutManager rectArrayForCharacterRange:NSMakeRange([NSArrayObjectAtIndex(lines, line) unsignedIntegerValue], 0) @@ -386,7 +396,7 @@ BOOL flipped = [self isFlipped]; - for (line = [self lineNumberForCharacterIndex: range.location]; line < count; line++) + for (line = (NSUInteger)(*lineNumberForCharacterIndexIMP)(self, lineNumberForCharacterIndexSel, range.location); line < count; line++) { index = [NSArrayObjectAtIndex(lines, line) unsignedIntegerValue]; @@ -777,17 +787,21 @@ index = 0; + // Cache loop methods for speed + IMP rangeOfLineIMP = [textString methodForSelector:rangeOfLineSel]; + addObjectIMP = [lineIndices methodForSelector:addObjectSel]; + do { - [lineIndices addObject: [NSNumber numberWithUnsignedInteger: index]]; - [textString getLineStart:NULL end:&index contentsEnd:NULL forRange:NSMakeRange(index, 0)]; + (void)(*addObjectIMP)(lineIndices, addObjectSel, (*numberWithUnsignedIntegerIMP)(numberClass, numberWithUnsignedIntegerSel, index)); + (*rangeOfLineIMP)(textString, rangeOfLineSel, NULL, &index, NULL, NSMakeRange(index, 0)); } while (index < stringLength); // Check if text ends with a new line. - [textString getLineStart:NULL end:&lineEnd contentsEnd:&contentEnd forRange:NSMakeRange([[lineIndices lastObject] intValue], 0)]; + (*rangeOfLineIMP)(textString, rangeOfLineSel, NULL, &lineEnd, &contentEnd, NSMakeRange([[lineIndices lastObject] intValue], 0)); if (contentEnd < lineEnd) - [lineIndices addObject: [NSNumber numberWithUnsignedInteger: index]]; + (void)(*addObjectIMP)(lineIndices, addObjectSel, (*numberWithUnsignedIntegerIMP)(numberClass, numberWithUnsignedIntegerSel, index)); NSUInteger lineCount = [lineIndices count]; if(lineCount < 100) diff --git RController.h RController.h index 0fba2c8..1648ead 100644 --- RController.h +++ RController.h @@ -92,6 +92,10 @@ WebView *currentWebViewForFindAction; id searchInWebViewWindow; + IMP _nextEventImp; + IMP _sendEventImp; + IMP _doProcessImp; + NSTimer *timer; NSTimer *RLtimer; NSTimer *Flushtimer; diff --git RController.m RController.m index 12df46b..0c19f7e 100644 --- RController.m +++ RController.m @@ -115,6 +115,10 @@ int R_SetOptionWidth(int); static RController* sharedRController; +static SEL _nextEventSel; +static SEL _sendEventSel; +static SEL _doProcessSel; + static inline const char* NSStringUTF8String(NSString* self) { typedef const char* (*SPUTF8StringMethodPtr)(NSString*, SEL); @@ -212,6 +216,14 @@ static inline const char* NSStringUTF8String(NSString* self) filteredHistory = nil; + _nextEventSel = @selector(nextEventMatchingMask:untilDate:inMode:dequeue:); + _sendEventSel = @selector(sendEvent:); + _doProcessSel = @selector(doProcessEvents:); + + _nextEventImp = [NSApp methodForSelector:_nextEventSel]; + _sendEventImp = [NSApp methodForSelector:_sendEventSel]; + _doProcessImp = [self methodForSelector:_doProcessSel]; + specialCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"\r\b\a"] retain]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -1402,7 +1414,7 @@ extern BOOL isTimeToFinish; while ([consoleInputQueue count]==0) { processingEvents = NO; // we should be at the top level, so for sanity reasons make sure we always process events - [self doProcessEvents: YES]; + (_doProcessImp)(self, _doProcessSel, YES); } currentConsoleInput = [consoleInputQueue objectAtIndex:0]; @@ -1703,8 +1715,9 @@ extern BOOL isTimeToFinish; // to be processed in all cases, even if system was called from within // the event handler and as such can run recursively NSEvent *event; - if((event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.05] inMode:NSDefaultRunLoopMode dequeue:YES])) - [NSApp sendEvent: event]; + if((event = (_nextEventImp)(NSApp, _nextEventSel, NSAnyEventMask, [NSDate dateWithTimeIntervalSinceNow:0.05], NSDefaultRunLoopMode, YES))) + (_sendEventImp)(NSApp, _sendEventSel, event); + } if(breakPending) { kill(pid, SIGINT); @@ -3100,11 +3113,11 @@ outputType: 0 = stdout, 1 = stderr, 2 = stdout/err as root #ifdef USE_POOLS NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; #endif - if (blocking) - [NSApp sendEvent: [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES]]; - else { - while((event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.0001] inMode:NSDefaultRunLoopMode dequeue:YES])) - [NSApp sendEvent: event]; + if (blocking){ + (_sendEventImp)(NSApp, _sendEventSel, (_nextEventImp)(NSApp, _nextEventSel, NSAnyEventMask, [NSDate distantFuture], NSDefaultRunLoopMode, YES)); + } else { + while((event = (_nextEventImp)(NSApp, _nextEventSel, NSAnyEventMask, [NSDate dateWithTimeIntervalSinceNow:0.0001], NSDefaultRunLoopMode, YES))) + (_sendEventImp)(NSApp, _sendEventSel, event); } #ifdef USE_POOLS [pool release]; @@ -3132,7 +3145,7 @@ outputType: 0 = stdout, 1 = stderr, 2 = stdout/err as root - (void) handleProcessEvents { - [self doProcessEvents: NO]; + (_doProcessImp)(self, _doProcessSel, NO); } diff --git RScriptEditorGlyphGenerator.h RScriptEditorGlyphGenerator.h index c9cab1e..80251cc 100644 --- RScriptEditorGlyphGenerator.h +++ RScriptEditorGlyphGenerator.h @@ -42,6 +42,9 @@ id _destination; RScriptEditorTextStorage *theTextStorage; NSGlyph nullGlyph; + IMP _attrStrImp; + IMP _foldImp; + IMP _foldindImp; NSInteger sizeOfNSGlyph; } diff --git RScriptEditorGlyphGenerator.m RScriptEditorGlyphGenerator.m index 464769c..82d0ab6 100644 --- RScriptEditorGlyphGenerator.m +++ RScriptEditorGlyphGenerator.m @@ -38,13 +38,27 @@ #import "RScriptEditorLayoutManager.h" #import "PreferenceKeys.h" +static SEL _attrStrSel; +static SEL _foldSel; +static SEL _foldindSel; + @implementation RScriptEditorGlyphGenerator ++ (void)initialize +{ + if ([self class] == [RScriptEditorGlyphGenerator class]) { + _attrStrSel = @selector(attributedString); + _foldSel = @selector(foldedRangeAtIndex:); + _foldindSel = @selector(foldedForIndicatorAtIndex:); + } +} + - (id)init { self = [super init]; if (self != nil) { + _attrStrImp = [self methodForSelector:_attrStrSel]; nullGlyph = NSNullGlyph; sizeOfNSGlyph = sizeof(NSGlyph); } @@ -61,6 +75,8 @@ { if(theTextStorage) [theTextStorage release]; theTextStorage = [textStorage retain]; + _foldImp = [theTextStorage methodForSelector:_foldSel]; + _foldindImp = [theTextStorage methodForSelector:_foldindSel]; } - (void)generateGlyphsForGlyphStorage:(id )glyphStorage desiredNumberOfCharacters:(NSUInteger)nChars glyphIndex:(NSUInteger *)glyphIndex characterIndex:(NSUInteger *)charIndex diff --git RScriptEditorTextStorage.h RScriptEditorTextStorage.h index f04f993..2879ca9 100644 --- RScriptEditorTextStorage.h +++ RScriptEditorTextStorage.h @@ -46,6 +46,13 @@ id selfDelegate; + IMP _getImp; + IMP _setImp; + IMP _strImp; + IMP _replImp; + IMP _editImp; + IMP _getlImp; + } - (id)initWithDelegate:(id)theDelegate; diff --git RScriptEditorTextStorage.m RScriptEditorTextStorage.m index e52d397..65d9844 100644 --- RScriptEditorTextStorage.m +++ RScriptEditorTextStorage.m @@ -77,6 +77,12 @@ static SEL _getlSel; if (self != nil) { _attributedString = [[NSTextStorage alloc] init]; + _getImp = [_attributedString methodForSelector:_getSel]; + _setImp = [_attributedString methodForSelector:_setSel]; + _strImp = [_attributedString methodForSelector:_strSel]; + _replImp = [_attributedString methodForSelector:_replSel]; + _editImp = [self methodForSelector:_editSel]; + _getlImp = [_attributedString methodForSelector:_getlSel]; selfDelegate = (RScriptEditorTextView*)theDelegate; [self setDelegate:theDelegate]; @@ -298,13 +304,13 @@ static SEL _getlSel; - (NSString *)string { - return _attributedString ? [_attributedString string] : nil; + return (*_strImp)(_attributedString, _strSel); } - (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range { - NSDictionary *attributes = [_attributedString attributesAtIndex:location effectiveRange:range]; + NSDictionary *attributes = (*_getImp)(_attributedString, _getSel, location, range); if(!foldedCounter || location > [_attributedString length]) return attributes; @@ -375,14 +381,14 @@ static SEL _getlSel; // NSMutableAttributedString primitives - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str { - [_attributedString replaceCharactersInRange:range withString:str]; - [self edited:NSTextStorageEditedCharacters range:range changeInLength: [str length] - range.length]; + (*_replImp)(_attributedString, _replSel, range, str); + (*_editImp)(self, _editSel, NSTextStorageEditedCharacters, range, [str length] - range.length); } - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range { - [_attributedString setAttributes:attrs range:range]; - [self edited:NSTextStorageEditedAttributes range:range changeInLength:0]; + (*_setImp)(_attributedString, _setSel, attrs, range); + (*_editImp)(self, _editSel, NSTextStorageEditedAttributes, range, 0); } // Attribute Fixing Overrides diff --git RScriptEditorTypeSetter.h RScriptEditorTypeSetter.h index a53688f..ded33e9 100644 --- RScriptEditorTypeSetter.h +++ RScriptEditorTypeSetter.h @@ -42,6 +42,7 @@ { RScriptEditorTextStorage *_attributedString; + IMP _foldImp; } diff --git RScriptEditorTypeSetter.m RScriptEditorTypeSetter.m index e9a20c7..b49771c 100644 --- RScriptEditorTypeSetter.m +++ RScriptEditorTypeSetter.m @@ -38,11 +38,14 @@ @implementation RScriptEditorTypeSetter +static SEL _foldSel; + - (id)init { self = [super init]; if (nil == self) return nil; _attributedString = nil; + _foldSel = @selector(foldedForIndicatorAtIndex:); return self; } @@ -56,12 +59,13 @@ { if(_attributedString) [_attributedString release]; _attributedString = [textStorage retain]; + _foldImp = [_attributedString methodForSelector:_foldSel]; + } - (NSTypesetterControlCharacterAction)actionForControlCharacterAtIndex:(NSUInteger)charIndex { - if (_attributedString && [_attributedString foldedForIndicatorAtIndex:charIndex] > -1) - return NSTypesetterZeroAdvancementAction; + if (_foldImp && (NSInteger)(*_foldImp)(_attributedString, _foldSel, charIndex) > -1) return NSTypesetterZeroAdvancementAction; return [super actionForControlCharacterAtIndex:charIndex]; } -- 2.48.0