diff --git a/ChangeLog b/ChangeLog index 79b500a1e..ccf2881fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2000-07-03 Richard Frith-Macdonald + + * Source/GSConnection.m: Cache coders fro performance. + * Source/GSPortCoder.m: support re-use. + * Source/GSTcpPort.m: tidy locking. + * Source/NSData.m: optimize +new + * Source/NSGCString.m: optimize -hash + * Source/NSGDictionary.m: optimize string hashing + * SourceNSObject.m: Call GSBuildStrings() for global constants. + * Source/NSPort.m: Create GSTcpPort by default. + * Source/externs.m: GSBuildStrings() now used to make string + constants that support cached hash values + * Tools/client.m: Added simple benchmarking. + * Tools/server.m: Added method for simple benchmarking. + * Tools/server.h: Added method for simple benchmarking. + 2000-07-02 Richard Frith-Macdonald * Source/GSConnection.m: Implementation almost complete diff --git a/Headers/gnustep/base/GSConnection.h b/Headers/gnustep/base/GSConnection.h index fe027d4e0..bfb485d05 100644 --- a/Headers/gnustep/base/GSConnection.h +++ b/Headers/gnustep/base/GSConnection.h @@ -82,6 +82,8 @@ GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */ NSMutableArray *_requestQueue; id _delegate; NSRecursiveLock *_refGate; + NSPortCoder *_cachedDecoder; + NSPortCoder *_cachedEncoder; } + (NSArray*) allConnections; diff --git a/Headers/gnustep/base/GSPortCoder.h b/Headers/gnustep/base/GSPortCoder.h index f530113cf..15cb185d7 100644 --- a/Headers/gnustep/base/GSPortCoder.h +++ b/Headers/gnustep/base/GSPortCoder.h @@ -1,4 +1,4 @@ -/* Interface for GSPortCoder object for distributed objects +/* Interface for NSPortCoder object for distributed objects Copyright (C) 2000 Free Software Foundation, Inc. Written by: Richard Frith-Macdonald @@ -21,15 +21,15 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#ifndef __GSPortCoder_h -#define __GSPortCoder_h +#ifndef __NSPortCoder_h +#define __NSPortCoder_h #include @class NSConnection; @class NSPort; -@interface GSPortCoder : NSCoder +@interface NSPortCoder : NSCoder { @private NSMutableArray *_comp; @@ -72,10 +72,10 @@ #ifndef _IN_PORT_CODER_M #undef GSIArray #endif + NSMutableArray *_cInfo; /* Class version information. */ unsigned _cursor; /* Position in data buffer. */ unsigned _version; /* Version of archiver used. */ NSZone *_zone; /* Zone for allocating objs. */ - NSMutableDictionary *_cInfo; /* Class information store. */ } + (NSPortCoder*) portCoderWithReceivePort: (NSPort*)recv @@ -99,4 +99,4 @@ @end -#endif /* __GSPortCoder_h */ +#endif /* __NSPortCoder_h */ diff --git a/Headers/gnustep/base/NSPort.h b/Headers/gnustep/base/NSPort.h index 2f53390c1..0f6bf74eb 100644 --- a/Headers/gnustep/base/NSPort.h +++ b/Headers/gnustep/base/NSPort.h @@ -62,9 +62,14 @@ GS_EXPORT NSString *NSPortTimeoutException; /* OPENSTEP */ forMode: (NSString*)aMode; - (unsigned) reservedSpaceLength; - (BOOL) sendBeforeDate: (NSDate*)when + msgid: (int)msgid components: (NSMutableArray*)components from: (NSPort*)receivingPort - reserved: (unsigned) length; + reserved: (unsigned)length; +- (BOOL) sendBeforeDate: (NSDate*)when + components: (NSMutableArray*)components + from: (NSPort*)receivingPort + reserved: (unsigned)length; #endif @end diff --git a/Source/GNUmakefile b/Source/GNUmakefile index a70c6c3a1..8a70e71c2 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -234,7 +234,6 @@ NSPipe.m \ NSPort.m \ GSTcpPort.m \ NSPortCoder.m \ -GSPortCoder.m \ NSPortMessage.m \ NSPortNameServer.m \ NSProcessInfo.m \ @@ -330,7 +329,6 @@ Foundation/NSObject.h \ Foundation/NSPathUtilities.h \ Foundation/NSPort.h \ Foundation/NSPortCoder.h \ -Foundation/GSPortCoder.h \ Foundation/NSPortMessage.h \ Foundation/NSPortNameServer.h \ Foundation/NSProcessInfo.h \ diff --git a/Source/GSConnection.m b/Source/GSConnection.m index 1066a5aa3..e1bda2ac2 100644 --- a/Source/GSConnection.m +++ b/Source/GSConnection.m @@ -202,9 +202,11 @@ static unsigned local_object_counter = 0; - (void) handlePortMessage: (NSPortMessage*)msg; - _getReplyRmc: (int)n; -- (NSPortCoder*) _makeRmc: (int)sequence; +- (void) _doneInRmc: (NSPortCoder*)c; +- (NSPortCoder*) _makeInRmc: (NSMutableArray*)components; +- (NSPortCoder*) _makeOutRmc: (int)sequence; - (int) _newMsgNumber; -- (void) _sendRmc: (NSPortCoder*)c type: (int)msgid; +- (void) _sendOutRmc: (NSPortCoder*)c type: (int)msgid; - (void) _service_forwardForProxy: (NSPortCoder*)rmc; - (void) _service_release: (NSPortCoder*)rmc; @@ -1010,11 +1012,12 @@ static int messages_received_count; NSParameterAssert(_isValid); seq_num = [self _newMsgNumber]; - op = [self _makeRmc: seq_num]; - [self _sendRmc: op type: ROOTPROXY_REQUEST]; + op = [self _makeOutRmc: seq_num]; + [self _sendOutRmc: op type: ROOTPROXY_REQUEST]; ip = [self _getReplyRmc: seq_num]; [ip decodeValueOfObjCType: @encode(id) at: &newProxy]; + DESTROY(ip); return AUTORELEASE(newProxy); } @@ -1187,6 +1190,9 @@ static int messages_received_count; _replyMap = 0; } + DESTROY(_cachedDecoder); + DESTROY(_cachedEncoder); + DESTROY(_refGate); RELEASE(arp); } @@ -1250,7 +1256,7 @@ static int messages_received_count; NSParameterAssert(*type); seq_num = [self _newMsgNumber]; - op = [self _makeRmc: seq_num]; + op = [self _makeOutRmc: seq_num]; if (debug_connection > 4) NSLog(@"building packet seq %d", seq_num); @@ -1268,7 +1274,7 @@ static int messages_received_count; won't be right for this machine! */ out_parameters = mframe_dissect_call (argframe, type, encoder); - [self _sendRmc: op type: METHOD_REQUEST]; + [self _sendOutRmc: op type: METHOD_REQUEST]; if (debug_connection > 1) NSLog(@"Sent message to 0x%x", (gsaddr)self); @@ -1284,8 +1290,10 @@ static int messages_received_count; { if (ip != nil) { + DESTROY(ip); /* this must be here to avoid trashing alloca'ed retframe */ ip = (id)-1; + _repInCount++; /* received a reply */ } return; } @@ -1308,6 +1316,7 @@ static int messages_received_count; /* Decode the exception object, and raise it. */ id exc; [ip decodeValueOfObjCType: @encode(id) at: &exc]; + DESTROY(ip); ip = (id)-1; /* xxx Is there anything else to clean up in dissect_method_return()? */ @@ -1332,7 +1341,6 @@ static int messages_received_count; if mframe_build_return() never called DECODER(), i.e. when we are just returning (void).*/ NSAssert(ip == (id)-1 || ip == nil, NSInternalInconsistencyException); - _repInCount++; /* received a reply */ return retframe; } } @@ -1347,12 +1355,13 @@ static int messages_received_count; NSParameterAssert(_receivePort); NSParameterAssert (_isValid); seq_num = [self _newMsgNumber]; - op = [self _makeRmc: seq_num]; + op = [self _makeOutRmc: seq_num]; [op encodeValueOfObjCType: ":" at: &sel]; [op encodeValueOfObjCType: @encode(unsigned) at: &target]; - [self _sendRmc: op type: METHODTYPE_REQUEST]; + [self _sendOutRmc: op type: METHODTYPE_REQUEST]; ip = [self _getReplyRmc: seq_num]; [ip decodeValueOfObjCType: @encode(char*) at: &type]; + DESTROY(ip); return type; } @@ -1440,9 +1449,8 @@ static int messages_received_count; } } - rmc = [NSPortCoder portCoderWithReceivePort: rp - sendPort: sp - components: components]; + rmc = [conn _makeInRmc: components]; + switch (type) { case ROOTPROXY_REQUEST: @@ -1486,12 +1494,10 @@ static int messages_received_count; while (conn->_requestDepth == 0 && [conn->_requestQueue count] > 0) { rmc = [conn->_requestQueue objectAtIndex: 0]; - RETAIN(rmc); [conn->_requestQueue removeObjectAtIndex: 0]; M_UNLOCK(conn->_queueGate); [conn _service_forwardForProxy: rmc]; M_LOCK(conn->_queueGate); - RELEASE(rmc); } M_UNLOCK(conn->_queueGate); break; @@ -1554,6 +1560,7 @@ static int messages_received_count; "-awake..." methods will get sent before the __builtin_apply! */ if (argnum == -1 && datum == 0 && type == 0) { + [self _doneInRmc: aRmc]; return; } @@ -1579,7 +1586,7 @@ static int messages_received_count; back to the remote application! */ if (!_isValid) return; - op = [self _makeRmc: reply_sequence_number]; + op = [self _makeOutRmc: reply_sequence_number]; [op encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; } switch (*type) @@ -1621,7 +1628,7 @@ static int messages_received_count; mframe_do_call (forward_type, decoder, encoder); if (op != nil) { - [self _sendRmc: op type: METHOD_REPLY]; + [self _sendOutRmc: op type: METHOD_REPLY]; } } @@ -1635,11 +1642,11 @@ static int messages_received_count; { NS_DURING { - op = [self _makeRmc: reply_sequence_number]; + op = [self _makeOutRmc: reply_sequence_number]; [op encodeValueOfObjCType: @encode(BOOL) at: &is_exception]; [op encodeBycopyObject: localException]; - [self _sendRmc: op type: METHOD_REPLY]; + [self _sendOutRmc: op type: METHOD_REPLY]; } NS_HANDLER { @@ -1667,9 +1674,10 @@ static int messages_received_count; NSParameterAssert([rmc connection] == self); [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; - op = [self _makeRmc: sequence]; + [self _doneInRmc: rmc]; + op = [self _makeOutRmc: sequence]; [op encodeObject: rootObject]; - [self _sendRmc: op type: ROOTPROXY_REPLY]; + [self _sendOutRmc: op type: ROOTPROXY_REPLY]; } - (void) _service_release: (NSPortCoder*)rmc @@ -1702,6 +1710,7 @@ static int messages_received_count; NSLog(@"releasing object with target (0x%x) on (0x%x) - nothing to do", target, (gsaddr)self); } + [self _doneInRmc: rmc]; } - (void) _service_retain: (NSPortCoder*)rmc @@ -1713,9 +1722,10 @@ static int messages_received_count; NSParameterAssert (_isValid); [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; - op = [self _makeRmc: sequence]; + op = [self _makeOutRmc: sequence]; [rmc decodeValueOfObjCType: @encode(typeof(target)) at: &target]; + [self _doneInRmc: rmc]; if (debug_connection > 3) NSLog(@"looking to retain local object with target (0x%x) on (0x%x)", @@ -1773,7 +1783,7 @@ static int messages_received_count; target, self); } - [self _sendRmc: op type: RETAIN_REPLY]; + [self _sendOutRmc: op type: RETAIN_REPLY]; } - (void) shutdown @@ -1782,13 +1792,14 @@ static int messages_received_count; NSParameterAssert(_receivePort); NSParameterAssert (_isValid); - op = [self _makeRmc: [self _newMsgNumber]]; - [self _sendRmc: op type: CONNECTION_SHUTDOWN]; + op = [self _makeOutRmc: [self _newMsgNumber]]; + [self _sendOutRmc: op type: CONNECTION_SHUTDOWN]; } - (void) _service_shutdown: (NSPortCoder*)rmc { NSParameterAssert (_isValid); + [self _doneInRmc: rmc]; [self invalidate]; [NSException raise: NSGenericException format: @"connection waiting for request was shut down"]; @@ -1809,10 +1820,11 @@ static int messages_received_count; NSParameterAssert (_isValid); [rmc decodeValueOfObjCType: @encode(int) at: &sequence]; - op = [self _makeRmc: sequence]; + op = [self _makeOutRmc: sequence]; [rmc decodeValueOfObjCType: ":" at: &sel]; [rmc decodeValueOfObjCType: @encode(unsigned) at: &target]; + [self _doneInRmc: rmc]; p = [self includesLocalTarget: target]; o = [p localForProxy]; @@ -1827,7 +1839,7 @@ static int messages_received_count; else type = ""; [op encodeValueOfObjCType: @encode(char*) at: &type]; - [self _sendRmc: op type: METHODTYPE_REPLY]; + [self _sendOutRmc: op type: METHODTYPE_REPLY]; } @@ -1869,23 +1881,15 @@ static int messages_received_count; } M_LOCK(_queueGate); } + if (rmc != nil) + { + RETAIN(rmc); + NSMapRemove(_replyMap, (void*)sn); + } M_UNLOCK(_queueGate); return rmc; } -- (NSPortCoder*) _makeRmc: (int)sequence -{ - NSPortCoder *coder; - - NSParameterAssert(_isValid); - - coder = [NSPortCoder portCoderWithReceivePort: [self receivePort] - sendPort: [self sendPort] - components: nil]; - [coder encodeValueOfObjCType: @encode(int) at: &sequence]; - return coder; -} - - (int) _newMsgNumber { int n; @@ -1897,9 +1901,74 @@ static int messages_received_count; return n; } -- (void) _sendRmc: (NSPortCoder*)c type: (int)msgid +- (void) _doneInRmc: (NSPortCoder*)c +{ + M_LOCK(_refGate); + if (_cachedDecoder == nil) + { + _cachedDecoder = c; + [c dispatch]; /* make coder release connection */ + } + else + { + RELEASE(c); + } + M_UNLOCK(_refGate); +} + +- (NSPortCoder*) _makeInRmc: (NSMutableArray*)components +{ + NSPortCoder *coder; + + NSParameterAssert(_isValid); + + M_LOCK(_refGate); + if (_cachedDecoder == nil) + { + coder = [NSPortCoder allocWithZone: NSDefaultMallocZone()]; + } + else + { + coder = _cachedDecoder; + _cachedDecoder = nil; + } + M_UNLOCK(_refGate); + + coder = [coder initWithReceivePort: _receivePort + sendPort: _sendPort + components: components]; + return coder; +} + +- (NSPortCoder*) _makeOutRmc: (int)sequence +{ + NSPortCoder *coder; + + NSParameterAssert(_isValid); + + M_LOCK(_refGate); + if (_cachedEncoder == nil) + { + coder = [NSPortCoder allocWithZone: NSDefaultMallocZone()]; + } + else + { + coder = _cachedEncoder; + _cachedEncoder = nil; + } + M_UNLOCK(_refGate); + + coder = [coder initWithReceivePort: _receivePort + sendPort: _sendPort + components: nil]; + [coder encodeValueOfObjCType: @encode(int) at: &sequence]; + return coder; +} + +- (void) _sendOutRmc: (NSPortCoder*)c type: (int)msgid { NSDate *limit; + BOOL sent = NO; BOOL raiseException = NO; NSMutableArray *components = [c _components]; @@ -1910,17 +1979,32 @@ static int messages_received_count; d = [[self delegate] authenticationDataForComponents: components]; if (d == nil) { + RELEASE(c); [NSException raise: NSGenericException format: @"Bad authentication data provided by delegate"]; } [components addObject: d]; } limit = [NSDate dateWithTimeIntervalSinceNow: [self requestTimeout]]; - if ([_sendPort sendBeforeDate: limit - msgid: msgid - components: components - from: _receivePort - reserved: [_sendPort reservedSpaceLength]] == NO) + sent = [_sendPort sendBeforeDate: limit + msgid: msgid + components: components + from: _receivePort + reserved: [_sendPort reservedSpaceLength]]; + + M_LOCK(_refGate); + if (_cachedEncoder == nil) + { + _cachedEncoder = c; + [c dispatch]; /* make coder release connection */ + } + else + { + RELEASE(c); + } + M_UNLOCK(_refGate); + + if (sent == NO) { NSString *text; @@ -2115,7 +2199,7 @@ static int messages_received_count; unsigned i; int sequence = [self _newMsgNumber]; - op = [self _makeRmc: sequence]; + op = [self _makeOutRmc: sequence]; [op encodeValueOfObjCType: @encode(unsigned) at: &number]; @@ -2127,7 +2211,7 @@ static int messages_received_count; list[i], (gsaddr)self); } - [self _sendRmc: op type: PROXY_RELEASE]; + [self _sendOutRmc: op type: PROXY_RELEASE]; } } NS_HANDLER @@ -2153,12 +2237,13 @@ static int messages_received_count; id result; int seq_num = [self _newMsgNumber]; - op = [self _makeRmc: seq_num]; + op = [self _makeOutRmc: seq_num]; [op encodeValueOfObjCType: @encode(typeof(target)) at: &target]; - [self _sendRmc: op type: PROXY_RETAIN]; + [self _sendOutRmc: op type: PROXY_RETAIN]; ip = [self _getReplyRmc: seq_num]; [ip decodeValueOfObjCType: @encode(id) at: &result]; + DESTROY(ip); if (result != nil) NSLog(@"failed to retain target - %@", result); } diff --git a/Source/GSPortCoder.m b/Source/GSPortCoder.m index ea47a8b1b..e61579b4a 100644 --- a/Source/GSPortCoder.m +++ b/Source/GSPortCoder.m @@ -240,8 +240,10 @@ typeCheck(char t1, char t2) @public Class class; unsigned version; + NSString *name; } + (id) newWithClass: (Class)c andVersion: (unsigned)v; +- (NSString*) className; @end @implementation GSClassInfo @@ -257,8 +259,17 @@ typeCheck(char t1, char t2) } return info; } +- (NSString*) className +{ + if (name == nil) + { + name = RETAIN(NSStringFromClass(class)); + } + return name; +} - (void) dealloc { + TEST_RELEASE(name); NSDeallocateObject(self); } @end @@ -278,8 +289,6 @@ typeCheck(char t1, char t2) classes: (unsigned)c objects: (unsigned)o pointers: (unsigned)p; -- (id) _setupForDecoding; -- (id) _setupForEncoding; @end @@ -622,7 +631,6 @@ typeCheck(char t1, char t2) while ((info & _GSC_MASK) == _GSC_CLASS) { unsigned cver; - NSString *className; if (xref != GSIArrayCount(_clsAry)) { @@ -637,14 +645,9 @@ typeCheck(char t1, char t2) [NSException raise: NSInternalInconsistencyException format: @"decoded nil class"]; } - className = NSStringFromClass(c); - classInfo = [_cInfo objectForKey: className]; - if (classInfo == nil) - { - classInfo = [GSClassInfo newWithClass: c andVersion: cver]; - [_cInfo setObject: classInfo forKey: className]; - RELEASE(classInfo); - } + classInfo = [GSClassInfo newWithClass: c andVersion: cver]; + [_cInfo addObject: classInfo]; + RELEASE(classInfo); GSIArrayAddItem(_clsAry, (GSIArrayItem)classInfo); *(Class*)address = classInfo->class; /* @@ -985,6 +988,12 @@ typeCheck(char t1, char t2) - (void) dispatch { + /* + * Get ready for re-use + * Make sure that we don't retain the connection - or it might never be + * released if it is keeping this coder in a cache. + */ + DESTROY(_conn); } - (void) encodeArrayOfObjCType: (const char*)type @@ -1610,24 +1619,180 @@ typeCheck(char t1, char t2) sendPort: (NSPort*)send components: (NSArray*)comp { - self = [super init]; - if (self != nil) + BOOL firstTime; + + _conn = RETAIN([NSConnection connectionWithReceivePort: recv + sendPort: send]); + if (_comp == nil) { + firstTime = YES; _version = [super systemVersion]; _zone = NSDefaultMallocZone(); - _conn = RETAIN([NSConnection connectionWithReceivePort: recv - sendPort: send]); + } + else + { + NSAssert(recv == [_conn receivePort] && send == [_conn sendPort], + NSInvalidArgumentException); + /* + * Re-initialising - destroy old components. + */ + firstTime = NO; + } - if (comp == nil) + if (comp == nil) + { + NS_DURING { - _comp = [NSMutableArray new]; - self = [self _setupForEncoding]; + _encodingRoot = NO; + _initialPass = NO; + _xRefC = 0; + _xRefO = 0; + _xRefP = 0; + + _cursor = [send reservedSpaceLength]; + if (firstTime == YES) + { + /* + * Set up mutable data object to encode into - reserve space at + * the start for use by the port when the encoded data is sent. + * Make the data item the first component of the array. + */ + _comp = [NSMutableArray new]; + _dst = [_fastCls._NSMutableDataMalloc allocWithZone: _zone]; + _dst = [_dst initWithLength: _cursor]; + [_comp addObject: _dst]; + RELEASE(_dst); + + /* + * Cache method implementations for writing into data object etc + */ + _eSerImp = [_dst methodForSelector: eSerSel]; + _eTagImp = [_dst methodForSelector: eTagSel]; + _xRefImp = [_dst methodForSelector: xRefSel]; + _eObjImp = [self methodForSelector: eObjSel]; + _eValImp = [self methodForSelector: eValSel]; + + /* + * Set up map tables. + */ + _clsMap + = (GSIMapTable)NSZoneMalloc(_zone, sizeof(GSIMapTable_t)*4); + _cIdMap = &_clsMap[1]; + _uIdMap = &_clsMap[2]; + _ptrMap = &_clsMap[3]; + GSIMapInitWithZoneAndCapacity(_clsMap, _zone, 100); + GSIMapInitWithZoneAndCapacity(_cIdMap, _zone, 10); + GSIMapInitWithZoneAndCapacity(_uIdMap, _zone, 200); + GSIMapInitWithZoneAndCapacity(_ptrMap, _zone, 100); + } + else + { + unsigned count; + + /* + * If re-initialising, we just need to empty the old stuff. + */ + count = [_comp count]; + while (count-- > 1) + { + [_comp removeObjectAtIndex: count]; + } + [_dst setLength: _cursor]; + GSIMapCleanMap(_clsMap); + GSIMapCleanMap(_cIdMap); + GSIMapCleanMap(_uIdMap); + GSIMapCleanMap(_ptrMap); + } + + /* + * Write dummy header + */ + [self _serializeHeaderAt: _cursor + version: 0 + classes: 0 + objects: 0 + pointers: 0]; } - else + NS_HANDLER { - _comp = [comp mutableCopy]; - self = [self _setupForDecoding]; + NSLog(@"Exception setting up port coder for encoding - %@", + localException); + DESTROY(self); } + NS_ENDHANDLER + } + else + { + RELEASE(_comp); + _comp = [comp mutableCopy]; + NS_DURING + { + unsigned sizeC; + unsigned sizeO; + unsigned sizeP; + + if (firstTime == YES) + { + _dValImp = [self methodForSelector: dValSel]; + } + _src = [_comp objectAtIndex: 0]; + _dDesImp = [_src methodForSelector: dDesSel]; + _dTagImp = (void (*)(id, SEL, unsigned char*, unsigned*, unsigned*)) + [_src methodForSelector: dTagSel]; + + /* + * _cInfo is a dictionary of objects for keeping track of the + * version numbers that the classes were encoded with. + */ + if (firstTime == YES) + { + _cInfo + = [[NSMutableArray allocWithZone: _zone] initWithCapacity: 16]; + } + else + { + [_cInfo removeAllObjects]; + } + + /* + * Read header including version and crossref table sizes. + */ + _cursor = 0; + [self _deserializeHeaderAt: &_cursor + version: &_version + classes: &sizeC + objects: &sizeO + pointers: &sizeP]; + + /* + * Allocate and initialise arrays to build crossref maps in. + */ + if (firstTime == YES) + { + _clsAry = NSZoneMalloc(_zone, sizeof(GSIArray_t)*3); + _objAry = &_clsAry[1]; + _ptrAry = &_clsAry[2]; + GSIArrayInitWithZoneAndCapacity(_clsAry, _zone, sizeC); + GSIArrayInitWithZoneAndCapacity(_objAry, _zone, sizeO); + GSIArrayInitWithZoneAndCapacity(_ptrAry, _zone, sizeP); + } + else + { + GSIArrayRemoveAllItems(_clsAry); + GSIArrayRemoveAllItems(_objAry); + GSIArrayRemoveAllItems(_ptrAry); + } + GSIArrayAddItem(_clsAry, (GSIArrayItem)0); + GSIArrayAddItem(_objAry, (GSIArrayItem)0); + GSIArrayAddItem(_ptrAry, (GSIArrayItem)0); + } + NS_HANDLER + { + NSLog(@"Exception setting up port coder for decoding - %@", + localException); + DESTROY(self); + } + NS_ENDHANDLER } return self; } @@ -1661,11 +1826,15 @@ typeCheck(char t1, char t2) { GSClassInfo *info; unsigned version = NSNotFound; + unsigned count = [_cInfo count]; - info = [_cInfo objectForKey: className]; - if (info != nil) + while (--count > 0) { - version = info->version; + info = [_cInfo objectAtIndex: count]; + if ([[info className] isEqual: className] == YES) + { + version = info->version; + } } return version; } @@ -1734,122 +1903,5 @@ typeCheck(char t1, char t2) } } -- (id) _setupForDecoding -{ - NS_DURING - { - unsigned sizeC; - unsigned sizeO; - unsigned sizeP; - - _dValImp = [self methodForSelector: dValSel]; - _src = [_comp objectAtIndex: 0]; - _dDesImp = [_src methodForSelector: dDesSel]; - _dTagImp = (void (*)(id, SEL, unsigned char*, unsigned*, unsigned*)) - [_src methodForSelector: dTagSel]; - - /* - * _cInfo is a dictionary of objects for keeping track of the - * version numbers that the classes were encoded with. - */ - _cInfo - = [[NSMutableDictionary allocWithZone: _zone] initWithCapacity: 200]; - - /* - * Read header including version and crossref table sizes. - */ - _cursor = 0; - [self _deserializeHeaderAt: &_cursor - version: &_version - classes: &sizeC - objects: &sizeO - pointers: &sizeP]; - - /* - * Allocate and initialise arrays to build crossref maps in. - */ - _clsAry = NSZoneMalloc(_zone, sizeof(GSIArray_t)*3); - GSIArrayInitWithZoneAndCapacity(_clsAry, _zone, sizeC); - GSIArrayAddItem(_clsAry, (GSIArrayItem)0); - - _objAry = &_clsAry[1]; - GSIArrayInitWithZoneAndCapacity(_objAry, _zone, sizeO); - GSIArrayAddItem(_objAry, (GSIArrayItem)0); - - _ptrAry = &_clsAry[2]; - GSIArrayInitWithZoneAndCapacity(_ptrAry, _zone, sizeP); - GSIArrayAddItem(_ptrAry, (GSIArrayItem)0); - } - NS_HANDLER - { - NSLog(@"Exception setting up port coder for decoding - %@", - localException); - DESTROY(self); - } - NS_ENDHANDLER - return self; -} - -- (id) _setupForEncoding -{ - NS_DURING - { - /* - * Set up mutable data object to encode into - reserve space at the - * start for use by the port when the encoded data is sent. - * Make the data item the first component of the array. - */ - _cursor = [[_conn sendPort] reservedSpaceLength]; - _dst = [_fastCls._NSMutableDataMalloc allocWithZone: fastZone(self)]; - _dst = [_dst initWithLength: _cursor]; - [_comp addObject: _dst]; - RELEASE(_dst); - - /* - * Cache method implementations for writing into data object etc - */ - _eSerImp = [_dst methodForSelector: eSerSel]; - _eTagImp = [_dst methodForSelector: eTagSel]; - _xRefImp = [_dst methodForSelector: xRefSel]; - _eObjImp = [self methodForSelector: eObjSel]; - _eValImp = [self methodForSelector: eValSel]; - - _encodingRoot = NO; - _initialPass = NO; - _xRefC = 0; - _xRefO = 0; - _xRefP = 0; - - /* - * Set up map tables. - */ - _clsMap = (GSIMapTable)NSZoneMalloc(_zone, sizeof(GSIMapTable_t)*4); - _cIdMap = &_clsMap[1]; - _uIdMap = &_clsMap[2]; - _ptrMap = &_clsMap[3]; - GSIMapInitWithZoneAndCapacity(_clsMap, _zone, 100); - GSIMapInitWithZoneAndCapacity(_cIdMap, _zone, 10); - GSIMapInitWithZoneAndCapacity(_uIdMap, _zone, 200); - GSIMapInitWithZoneAndCapacity(_ptrMap, _zone, 100); - - /* - * Write dummy header - */ - [self _serializeHeaderAt: _cursor - version: 0 - classes: 0 - objects: 0 - pointers: 0]; - } - NS_HANDLER - { - NSLog(@"Exception setting up port coder for encoding - %@", - localException); - DESTROY(self); - } - NS_ENDHANDLER - return self; -} - @end diff --git a/Source/GSTcpPort.m b/Source/GSTcpPort.m index 61369fbf8..9bbce5aef 100644 --- a/Source/GSTcpPort.m +++ b/Source/GSTcpPort.m @@ -254,7 +254,7 @@ decodePort(NSData *data) } static NSData* -encodePort(GSTcpPort *port) +newDataWithEncodedPort(GSTcpPort *port) { GSPortItemHeader *pih; GSPortInfo *pi; @@ -288,7 +288,7 @@ encodePort(GSTcpPort *port) } } plen = [addr cStringLength] + 3; - data = [NSMutableData dataWithLength: sizeof(GSPortItemHeader) + plen]; + data = [[NSMutableData alloc] initWithLength: sizeof(GSPortItemHeader)+plen]; pih = (GSPortItemHeader*)[data mutableBytes]; pih->type = GSSwapHostI32ToBig(GSP_PORT); pih->length = GSSwapHostI32ToBig(plen); @@ -488,13 +488,15 @@ encodePort(GSTcpPort *port) { NSPortMessage *pm; - pm = [[NSPortMessage alloc] initWithSendPort: [self sendPort] - receivePort: [self recvPort] - components: rItems]; + pm = [NSPortMessage allocWithZone: NSDefaultMallocZone()]; + pm = [pm initWithSendPort: [self sendPort] + receivePort: [self recvPort] + components: rItems]; [pm setMsgid: rId]; rId = 0; DESTROY(rItems); - [[self recvPort] handlePortMessage: AUTORELEASE(pm)]; + [[self recvPort] handlePortMessage: pm]; + RELEASE(pm); } - (void) gcFinalize @@ -596,7 +598,7 @@ encodePort(GSTcpPort *port) [self invalidate]; return; } - else if (errno != EINTR) + else if (errno != EINTR && errno != EAGAIN) { NSLog(@"read attempt failed - %s", strerror(errno)); [self invalidate]; @@ -634,6 +636,8 @@ encodePort(GSTcpPort *port) } else if (rType == GSP_DATA && l == 0) { + NSData *d; + /* * For a zero-length data chunk, we create an empty * data object and add it to the current message. @@ -644,7 +648,9 @@ encodePort(GSTcpPort *port) memcpy(bytes, bytes + rWant, rLength); } rWant = sizeof(GSPortItemHeader); - [rItems addObject: [NSData data]]; + d = [NSData new]; + [rItems addObject: d]; + RELEASE(d); if (nItems == [rItems count]) { [self dispatch]; @@ -799,7 +805,7 @@ encodePort(GSTcpPort *port) } else { - NSData *d = encodePort([self recvPort]); + NSData *d = newDataWithEncodedPort([self recvPort]); len = write(desc, [d bytes], [d length]); if (len == [d length]) @@ -812,6 +818,7 @@ encodePort(GSTcpPort *port) state = GS_H_UNCON; NSLog(@"connect write attempt failed - %s", strerror(errno)); } + RELEASE(d); } } else @@ -840,7 +847,7 @@ encodePort(GSTcpPort *port) res = write(desc, b + wLength, l - wLength); if (res < 0) { - if (errno != EINTR) + if (errno != EINTR && errno != EAGAIN) { NSLog(@"write attempt failed - %s", strerror(errno)); [self invalidate]; @@ -1631,7 +1638,7 @@ static NSMapTable *tcpPortMap = 0; NSMutableData *d; pack = NO; - d = [NSMutableData dataWithLength: l + h]; + d = [[NSMutableData alloc] initWithLength: l + h]; b = [d mutableBytes]; pih = (GSPortItemHeader*)b; memcpy(b+h, [o bytes], l); @@ -1639,11 +1646,12 @@ static NSMapTable *tcpPortMap = 0; pih->length = GSSwapHostI32ToBig(l); [components replaceObjectAtIndex: i withObject: d]; + RELEASE(d); } } else if ([o isKindOfClass: [GSTcpPort class]]) { - NSData *d = encodePort(o); + NSData *d = newDataWithEncodedPort(o); unsigned dLength = [d length]; if (pack == YES && hLength + dLength <= NETBLOCK) @@ -1663,6 +1671,7 @@ static NSMapTable *tcpPortMap = 0; pack = NO; [components replaceObjectAtIndex: i withObject: d]; } + RELEASE(d); } } diff --git a/Source/NSData.m b/Source/NSData.m index 4e7d43d1e..9f9c5865c 100644 --- a/Source/NSData.m +++ b/Source/NSData.m @@ -107,6 +107,7 @@ * these are set up at process startup or in [NSData +initialize] */ static SEL appendSel = @selector(appendBytes:length:); +static Class dataStatic; static Class dataMalloc; static Class mutableDataMalloc; static IMP appendImp; @@ -326,6 +327,7 @@ failure: if (self == [NSData class]) { dataMalloc = [NSDataMalloc class]; + dataStatic = [NSDataStatic class]; mutableDataMalloc = [NSMutableDataMalloc class]; appendImp = [mutableDataMalloc instanceMethodForSelector: appendSel]; } @@ -397,6 +399,15 @@ failure: return AUTORELEASE(d); } ++ (id) new +{ + NSData *d; + + d = [dataMalloc allocWithZone: NSDefaultMallocZone()]; + d = [d initWithBytesNoCopy: 0 length: 0 fromZone: NSDefaultMallocZone()]; + return d; +} + - (id) init { return [self initWithBytesNoCopy: 0 length: 0]; @@ -1335,6 +1346,15 @@ failure: return AUTORELEASE(d); } ++ (id) new +{ + NSMutableData *d; + + d = [mutableDataMalloc allocWithZone: NSDefaultMallocZone()]; + d = [d initWithCapacity: 0]; + return d; +} + - (const void*) bytes { return [self mutableBytes]; diff --git a/Source/NSGCString.m b/Source/NSGCString.m index aa7254788..b004cb454 100644 --- a/Source/NSGCString.m +++ b/Source/NSGCString.m @@ -101,7 +101,7 @@ static IMP msInitImp; /* designated initialiser for mutable */ return NSAllocateObject(self, 0, NSDefaultMallocZone()); } -- (void)dealloc +- (void) dealloc { if (_zone) { @@ -114,9 +114,7 @@ static IMP msInitImp; /* designated initialiser for mutable */ - (unsigned) hash { if (_hash == 0) - { - _hash = _fastImp._NSString_hash(self, @selector(hash)); - } + _hash = _fastImp._NSString_hash(self, @selector(hash)); return _hash; } @@ -1276,7 +1274,35 @@ stringDecrementCountAndFillHoleAt(NSGMutableCStringStruct *self, - (unsigned) hash { - return _fastImp._NSString_hash(self, @selector(hash)); + unsigned ret = 0; + + int len = _count; + + if (len > NSHashStringLength) + len = NSHashStringLength; + if (len) + { + const unsigned char *p; + unsigned char_count = 0; + + p = _contents_chars; + while (*p && char_count++ < NSHashStringLength) + { + ret = (ret << 5) + ret + *p++; + } + + /* + * The hash caching in our concrete string classes uses zero to denote + * an empty cache value, so we MUST NOT return a hash of zero. + */ + if (ret == 0) + ret = 0xffffffff; + } + else + { + ret = 0xfffffffe; /* Hash for an empty string. */ + } + return ret; } - (BOOL) isEqual: (id)anObject diff --git a/Source/NSGDictionary.m b/Source/NSGDictionary.m index 63e3c6a92..32f1290dd 100644 --- a/Source/NSGDictionary.m +++ b/Source/NSGDictionary.m @@ -63,7 +63,14 @@ myHash(id obj) } else if (c == _fastCls._NXConstantString) { - return _fastImp._NSString_hash(obj, @selector(hash)); + static unsigned (*myImp)(id,SEL) = 0; + + if (myImp == 0) + { + myImp = (unsigned (*)(id,SEL)) + [obj methodForSelector: @selector(hash)]; + } + return (*myImp)(obj, @selector(hash)); } } return [obj hash]; diff --git a/Source/NSObject.m b/Source/NSObject.m index 4c4eb4217..7da768ae7 100644 --- a/Source/NSObject.m +++ b/Source/NSObject.m @@ -595,6 +595,7 @@ static BOOL double_release_check_enabled = NO; { if (self == [NSObject class]) { + extern void GSBuildStrings(); // See externs.m #ifdef __FreeBSD__ // Manipulate the FPU to add the exception mask. (Fixes SIGFPE // problems on *BSD) @@ -621,6 +622,7 @@ static BOOL double_release_check_enabled = NO; fastMallocOffset = 0; #endif _fastBuildCache(); + GSBuildStrings(); [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_becomeMultiThreaded:) diff --git a/Source/NSPort.m b/Source/NSPort.m index 1d43fc721..24c275301 100644 --- a/Source/NSPort.m +++ b/Source/NSPort.m @@ -35,17 +35,22 @@ @implementation NSPort +Class _abstractClass; Class _concreteClass; + (id) allocWithZone: (NSZone*)aZone { - return [super allocWithZone: aZone]; + if (self == _abstractClass) + return NSAllocateObject(_concreteClass, 0, aZone); + else + return [super allocWithZone: aZone]; } + (void) initialize { if (self == [NSPort class]) { + _abstractClass = self; _concreteClass = [GSTcpPort class]; } } @@ -148,7 +153,7 @@ Class _concreteClass; - (void) setDelegate: (id) anObject { NSAssert([anObject respondsToSelector: @selector(handlePortMessage:)], - NSInvalidArgumentException); + NSInvalidArgumentException); _delegate = anObject; } diff --git a/Source/externs.m b/Source/externs.m index ee37f54cb..6e08917a9 100644 --- a/Source/externs.m +++ b/Source/externs.m @@ -22,86 +22,69 @@ */ #include -#include #include + + +#include #include #include #include "NSCallBacks.h" #include -#include /* Global lock to be used by classes when operating on any global data that invoke other methods which also access global; thus, creating the potential for deadlock. */ +@class NSRecursiveLock; NSRecursiveLock *gnustep_global_lock = nil; /* * Connection Notification Strings. */ -NSString* const NSConnectionDidDieNotification - = @"NSConnectionDidDieNotification"; -NSString* const NSConnectionDidInitializeNotification - = @"NSConnectionDidInitializeNotification"; +NSString *NSConnectionDidDieNotification; +NSString *NSConnectionDidInitializeNotification; /* * NSThread Notifications */ -NSString* const NSWillBecomeMultiThreadedNotification - = @"NSWillBecomeMultiThreadedNotification"; -NSString* const NSThreadWillExitNotification - = @"NSThreadWillExitNotification"; +NSString *NSWillBecomeMultiThreadedNotification; +NSString *NSThreadWillExitNotification; /* * Port Notifications */ -NSString* const PortBecameInvalidNotification = -@"PortBecameInvalidNotification"; -NSString* const InPortClientBecameInvalidNotification = -@"InPortClientBecameInvalidNotification"; -NSString* const InPortAcceptedClientNotification = -@"InPortAcceptedClientNotification"; +NSString *PortBecameInvalidNotification; +NSString *InPortClientBecameInvalidNotification; +NSString *InPortAcceptedClientNotification; -NSString* const NSPortDidBecomeInvalidNotification - = @"NSPortDidBecomeInvalidNotification"; +NSString *NSPortDidBecomeInvalidNotification; /* RunLoop modes */ -NSString* const NSDefaultRunLoopMode - = @"NSDefaultRunLoopMode"; -NSString* const NSConnectionReplyMode - = @"NSConnectionReplyMode"; +NSString *NSDefaultRunLoopMode; +NSString *NSConnectionReplyMode; /* Exceptions */ -NSString* const NSCharacterConversionException - = @"NSCharacterConversionException"; -NSString* const NSFailedAuthenticationException - = @"NSFailedAuthenticationException"; -NSString* const NSGenericException - = @"NSGenericException"; -NSString* const NSInconsistentArchiveException - = @"NSInconsistentArchiveException"; -NSString* const NSInternalInconsistencyException - = @"NSInternalInconsistencyException"; -NSString* const NSInvalidArgumentException - = @"NSInvalidArgumentException"; -NSString* const NSMallocException - = @"NSMallocException"; -NSString* const NSPortTimeoutException - = @"NSPortTimeoutException"; -NSString* const NSRangeException - = @"NSRangeException"; +NSString *NSCharacterConversionException; +NSString *NSFailedAuthenticationException; +NSString *NSGenericException; +NSString *NSInconsistentArchiveException; +NSString *NSInternalInconsistencyException; +NSString *NSInvalidArgumentException; +NSString *NSMallocException; +NSString *NSPortTimeoutException; +NSString *NSRangeException; /* Exception handler */ NSUncaughtExceptionHandler *_NSUncaughtExceptionHandler; /* NSBundle */ -NSString* const NSBundleDidLoadNotification = @"NSBundleDidLoadNotification"; -NSString* const NSShowNonLocalizedStrings = @"NSShowNonLocalizedStrings"; -NSString* const NSLoadedClasses = @"NSLoadedClasses"; +NSString *NSBundleDidLoadNotification; +NSString *NSShowNonLocalizedStrings; +NSString *NSLoadedClasses; /* Stream */ -NSString* const StreamException = @"StreamException"; +NSString *StreamException; /* * File attributes names @@ -109,141 +92,271 @@ NSString* const StreamException = @"StreamException"; /* File Attributes */ -NSString* const NSFileDeviceIdentifier - = @"NSFileDeviceIdentifier"; -NSString* const NSFileGroupOwnerAccountName - = @"NSFileGroupOwnerAccountName"; -NSString* const NSFileGroupOwnerAccountNumber - = @"NSFileGroupOwnerAccountNumber"; -NSString* const NSFileModificationDate - = @"NSFileModificationDate"; -NSString* const NSFileOwnerAccountName - = @"NSFileOwnerAccountName"; -NSString* const NSFileOwnerAccountNumber - = @"NSFileOwnerAccountNumber"; -NSString* const NSFilePosixPermissions - = @"NSFilePosixPermissions"; -NSString* const NSFileReferenceCount - = @"NSFileReferenceCount"; -NSString* const NSFileSize - = @"NSFileSize"; -NSString* const NSFileSystemFileNumber - = @"NSFileSystemFileNumber"; -NSString* const NSFileSystemNumber - = @"NSFileSystemNumber"; -NSString* const NSFileType - = @"NSFileType"; +NSString *NSFileDeviceIdentifier; +NSString *NSFileGroupOwnerAccountName; +NSString *NSFileGroupOwnerAccountNumber; +NSString *NSFileModificationDate; +NSString *NSFileOwnerAccountName; +NSString *NSFileOwnerAccountNumber; +NSString *NSFilePosixPermissions; +NSString *NSFileReferenceCount; +NSString *NSFileSize; +NSString *NSFileSystemFileNumber; +NSString *NSFileSystemNumber; +NSString *NSFileType; /* File Types */ -NSString* const NSFileTypeDirectory - = @"NSFileTypeDirectory"; -NSString* const NSFileTypeRegular - = @"NSFileTypeRegular"; -NSString* const NSFileTypeSymbolicLink - = @"NSFileTypeSymbolicLink"; -NSString* const NSFileTypeSocket - = @"NSFileTypeSocket"; -NSString* const NSFileTypeFifo - = @"NSFileTypeFifo"; -NSString* const NSFileTypeCharacterSpecial - = @"NSFileTypeCharacterSpecial"; -NSString* const NSFileTypeBlockSpecial - = @"NSFileTypeBlockSpecial"; -NSString* const NSFileTypeUnknown - = @"NSFileTypeUnknown"; +NSString *NSFileTypeDirectory; +NSString *NSFileTypeRegular; +NSString *NSFileTypeSymbolicLink; +NSString *NSFileTypeSocket; +NSString *NSFileTypeFifo; +NSString *NSFileTypeCharacterSpecial; +NSString *NSFileTypeBlockSpecial; +NSString *NSFileTypeUnknown; /* FileSystem Attributes */ -NSString* const NSFileSystemSize - = @"NSFileSystemSize"; -NSString* const NSFileSystemFreeSize - = @"NSFileSystemFreeSize"; -NSString* const NSFileSystemNodes - = @"NSFileSystemNodes"; -NSString* const NSFileSystemFreeNodes - = @"NSFileSystemFreeNodes"; +NSString *NSFileSystemSize; +NSString *NSFileSystemFreeSize; +NSString *NSFileSystemNodes; +NSString *NSFileSystemFreeNodes; /* Standard domains */ -NSString* const NSArgumentDomain - = @"NSArgumentDomain"; -NSString* const NSGlobalDomain - = @"NSGlobalDomain"; -NSString* const NSRegistrationDomain - = @"NSRegistrationDomain"; +NSString *NSArgumentDomain; +NSString *NSGlobalDomain; +NSString *NSRegistrationDomain; /* Public notification */ -NSString* const NSUserDefaultsDidChangeNotification - = @"NSUserDefaultsDidChangeNotification"; +NSString *NSUserDefaultsDidChangeNotification; /* Keys for language-dependent information */ -NSString* const NSWeekDayNameArray - = @"NSWeekDayNameArray"; -NSString* const NSShortWeekDayNameArray - = @"NSShortWeekDayNameArray"; -NSString* const NSMonthNameArray - = @"NSMonthNameArray"; -NSString* const NSShortMonthNameArray - = @"NSShortMonthNameArray"; -NSString* const NSTimeFormatString - = @"NSTimeFormatString"; -NSString* const NSDateFormatString - = @"NSDateFormatString"; -NSString* const NSTimeDateFormatString - = @"NSTimeDateFormatString"; -NSString* const NSShortTimeDateFormatString - = @"NSShortTimeDateFormatString"; -NSString* const NSCurrencySymbol - = @"NSCurrencySymbol"; -NSString* const NSDecimalSeparator - = @"NSDecimalSeparator"; -NSString* const NSThousandsSeparator - = @"NSThousandsSeparator"; -NSString* const NSInternationalCurrencyString - = @"NSInternationalCurrencyString"; -NSString* const NSCurrencyString - = @"NSCurrencyString"; -NSString* const NSDecimalDigits - = @"NSDecimalDigits"; -NSString* const NSAMPMDesignation - = @"NSAMPMDesignation"; +NSString *NSWeekDayNameArray; +NSString *NSShortWeekDayNameArray; +NSString *NSMonthNameArray; +NSString *NSShortMonthNameArray; +NSString *NSTimeFormatString; +NSString *NSDateFormatString; +NSString *NSTimeDateFormatString; +NSString *NSShortTimeDateFormatString; +NSString *NSCurrencySymbol; +NSString *NSDecimalSeparator; +NSString *NSThousandsSeparator; +NSString *NSInternationalCurrencyString; +NSString *NSCurrencyString; +NSString *NSDecimalDigits; +NSString *NSAMPMDesignation; -NSString* const NSHourNameDesignations - = @"NSHourNameDesignations"; -NSString* const NSYearMonthWeekDesignations - = @"NSYearMonthWeekDesignations"; -NSString* const NSEarlierTimeDesignations - = @"NSEarlierTimeDesignations"; -NSString* const NSLaterTimeDesignations - = @"NSLaterTimeDesignations"; -NSString* const NSThisDayDesignations - = @"NSThisDayDesignations"; -NSString* const NSNextDayDesignations - = @"NSNextDayDesignations"; -NSString* const NSNextNextDayDesignations - = @"NSNextNextDayDesignations"; -NSString* const NSPriorDayDesignations - = @"NSPriorDayDesignations"; -NSString* const NSDateTimeOrdering - = @"NSDateTimeOrdering"; +NSString *NSHourNameDesignations; +NSString *NSYearMonthWeekDesignations; +NSString *NSEarlierTimeDesignations; +NSString *NSLaterTimeDesignations; +NSString *NSThisDayDesignations; +NSString *NSNextDayDesignations; +NSString *NSNextNextDayDesignations; +NSString *NSPriorDayDesignations; +NSString *NSDateTimeOrdering; /* * Keys for the NSDictionary returned by [NSConnection -statistics] */ /* These in OPENSTEP 4.2 */ -NSString* const NSConnectionRepliesReceived - = @"NSConnectionRepliesReceived"; -NSString* const NSConnectionRepliesSent - = @"NSConnectionRepliesSent"; -NSString* const NSConnectionRequestsReceived - = @"NSConnectionRequestsReceived"; -NSString* const NSConnectionRequestsSent - = @"NSConnectionRequestsSent"; +NSString *NSConnectionRepliesReceived; +NSString *NSConnectionRepliesSent; +NSString *NSConnectionRequestsReceived; +NSString *NSConnectionRequestsSent; /* These Are GNUstep extras */ -NSString* const NSConnectionLocalCount - = @"NSConnectionLocalCount"; -NSString* const NSConnectionProxyCount - = @"NSConnectionProxyCount"; +NSString *NSConnectionLocalCount; +NSString *NSConnectionProxyCount; + +/* + * Setup function called when NSObject is initialised. + * We make all the constant strings not be NXConstantString so they can + * cache their hash values and be used much more efficiently as keys in + * dictionaries etc. + */ +void +GSBuildStrings() +{ + static BOOL beenHere = NO; + + if (beenHere == NO) + { + beenHere = YES; + InPortAcceptedClientNotification + = [[NSString alloc] initWithCString: + "InPortAcceptedClientNotification"]; + InPortClientBecameInvalidNotification + = [[NSString alloc] initWithCString: + "InPortClientBecameInvalidNotification"]; + NSAMPMDesignation + = [[NSString alloc] initWithCString: "NSAMPMDesignation"]; + NSArgumentDomain + = [[NSString alloc] initWithCString: "NSArgumentDomain"]; + NSBundleDidLoadNotification + = [[NSString alloc] initWithCString: "NSBundleDidLoadNotification"]; + NSCharacterConversionException + = [[NSString alloc] initWithCString: "NSCharacterConversionException"]; + NSConnectionDidDieNotification + = [[NSString alloc] initWithCString: "NSConnectionDidDieNotification"]; + NSConnectionDidInitializeNotification + = [[NSString alloc] initWithCString: + "NSConnectionDidInitializeNotification"]; + NSConnectionLocalCount + = [[NSString alloc] initWithCString: "NSConnectionLocalCount"]; + NSConnectionProxyCount + = [[NSString alloc] initWithCString: "NSConnectionProxyCount"]; + NSConnectionRepliesReceived + = [[NSString alloc] initWithCString: "NSConnectionRepliesReceived"]; + NSConnectionRepliesSent + = [[NSString alloc] initWithCString: "NSConnectionRepliesSent"]; + NSConnectionReplyMode + = [[NSString alloc] initWithCString: "NSConnectionReplyMode"]; + NSConnectionRequestsReceived + = [[NSString alloc] initWithCString: "NSConnectionRequestsReceived"]; + NSConnectionRequestsSent + = [[NSString alloc] initWithCString: "NSConnectionRequestsSent"]; + NSCurrencyString + = [[NSString alloc] initWithCString: "NSCurrencyString"]; + NSCurrencySymbol + = [[NSString alloc] initWithCString: "NSCurrencySymbol"]; + NSDateFormatString + = [[NSString alloc] initWithCString: "NSDateFormatString"]; + NSDateTimeOrdering + = [[NSString alloc] initWithCString: "NSDateTimeOrdering"]; + NSDecimalDigits + = [[NSString alloc] initWithCString: "NSDecimalDigits"]; + NSDecimalSeparator + = [[NSString alloc] initWithCString: "NSDecimalSeparator"]; + NSDefaultRunLoopMode + = [[NSString alloc] initWithCString: "NSDefaultRunLoopMode"]; + NSEarlierTimeDesignations + = [[NSString alloc] initWithCString: "NSEarlierTimeDesignations"]; + NSFailedAuthenticationException + = [[NSString alloc] initWithCString: "NSFailedAuthenticationException"]; + NSFileDeviceIdentifier + = [[NSString alloc] initWithCString: "NSFileDeviceIdentifier"]; + NSFileGroupOwnerAccountName + = [[NSString alloc] initWithCString: "NSFileGroupOwnerAccountName"]; + NSFileGroupOwnerAccountNumber + = [[NSString alloc] initWithCString: "NSFileGroupOwnerAccountNumber"]; + NSFileModificationDate + = [[NSString alloc] initWithCString: "NSFileModificationDate"]; + NSFileOwnerAccountName + = [[NSString alloc] initWithCString: "NSFileOwnerAccountName"]; + NSFileOwnerAccountNumber + = [[NSString alloc] initWithCString: "NSFileOwnerAccountNumber"]; + NSFilePosixPermissions + = [[NSString alloc] initWithCString: "NSFilePosixPermissions"]; + NSFileReferenceCount + = [[NSString alloc] initWithCString: "NSFileReferenceCount"]; + NSFileSize + = [[NSString alloc] initWithCString: "NSFileSize"]; + NSFileSystemFileNumber + = [[NSString alloc] initWithCString: "NSFileSystemFileNumber"]; + NSFileSystemFreeNodes + = [[NSString alloc] initWithCString: "NSFileSystemFreeNodes"]; + NSFileSystemFreeSize + = [[NSString alloc] initWithCString: "NSFileSystemFreeSize"]; + NSFileSystemNodes + = [[NSString alloc] initWithCString: "NSFileSystemNodes"]; + NSFileSystemNumber + = [[NSString alloc] initWithCString: "NSFileSystemNumber"]; + NSFileSystemSize + = [[NSString alloc] initWithCString: "NSFileSystemSize"]; + NSFileType + = [[NSString alloc] initWithCString: "NSFileType"]; + NSFileTypeBlockSpecial + = [[NSString alloc] initWithCString: "NSFileTypeBlockSpecial"]; + NSFileTypeCharacterSpecial + = [[NSString alloc] initWithCString: "NSFileTypeCharacterSpecial"]; + NSFileTypeDirectory + = [[NSString alloc] initWithCString: "NSFileTypeDirectory"]; + NSFileTypeFifo + = [[NSString alloc] initWithCString: "NSFileTypeFifo"]; + NSFileTypeRegular + = [[NSString alloc] initWithCString: "NSFileTypeRegular"]; + NSFileTypeSocket + = [[NSString alloc] initWithCString: "NSFileTypeSocket"]; + NSFileTypeSymbolicLink + = [[NSString alloc] initWithCString: "NSFileTypeSymbolicLink"]; + NSFileTypeUnknown + = [[NSString alloc] initWithCString: "NSFileTypeUnknown"]; + NSGenericException + = [[NSString alloc] initWithCString: "NSGenericException"]; + NSGlobalDomain + = [[NSString alloc] initWithCString: "NSGlobalDomain"]; + NSHourNameDesignations + = [[NSString alloc] initWithCString: "NSHourNameDesignations"]; + NSInconsistentArchiveException + = [[NSString alloc] initWithCString: "NSInconsistentArchiveException"]; + NSInternalInconsistencyException + = [[NSString alloc] initWithCString: + "NSInternalInconsistencyException"]; + NSInternationalCurrencyString + = [[NSString alloc] initWithCString: "NSInternationalCurrencyString"]; + NSInvalidArgumentException + = [[NSString alloc] initWithCString: "NSInvalidArgumentException"]; + NSLaterTimeDesignations + = [[NSString alloc] initWithCString: "NSLaterTimeDesignations"]; + NSLoadedClasses + = [[NSString alloc] initWithCString: "NSLoadedClasses"]; + NSMallocException + = [[NSString alloc] initWithCString: "NSMallocException"]; + NSMonthNameArray + = [[NSString alloc] initWithCString: "NSMonthNameArray"]; + NSNextDayDesignations + = [[NSString alloc] initWithCString: "NSNextDayDesignations"]; + NSNextNextDayDesignations + = [[NSString alloc] initWithCString: "NSNextNextDayDesignations"]; + NSPortDidBecomeInvalidNotification + = [[NSString alloc] initWithCString: + "NSPortDidBecomeInvalidNotification"]; + NSPortTimeoutException + = [[NSString alloc] initWithCString: "NSPortTimeoutException"]; + NSPriorDayDesignations + = [[NSString alloc] initWithCString: "NSPriorDayDesignations"]; + NSRangeException + = [[NSString alloc] initWithCString: "NSRangeException"]; + NSRegistrationDomain + = [[NSString alloc] initWithCString: "NSRegistrationDomain"]; + NSShortMonthNameArray + = [[NSString alloc] initWithCString: "NSShortMonthNameArray"]; + NSShortTimeDateFormatString + = [[NSString alloc] initWithCString: "NSShortTimeDateFormatString"]; + NSShortWeekDayNameArray + = [[NSString alloc] initWithCString: "NSShortWeekDayNameArray"]; + NSShowNonLocalizedStrings + = [[NSString alloc] initWithCString: "NSShowNonLocalizedStrings"]; + NSThisDayDesignations + = [[NSString alloc] initWithCString: "NSThisDayDesignations"]; + NSThousandsSeparator + = [[NSString alloc] initWithCString: "NSThousandsSeparator"]; + NSThreadWillExitNotification + = [[NSString alloc] initWithCString: "NSThreadWillExitNotification"]; + NSTimeDateFormatString + = [[NSString alloc] initWithCString: "NSTimeDateFormatString"]; + NSTimeFormatString + = [[NSString alloc] initWithCString: "NSTimeFormatString"]; + NSUserDefaultsDidChangeNotification + = [[NSString alloc] initWithCString: + "NSUserDefaultsDidChangeNotification"]; + NSWeekDayNameArray + = [[NSString alloc] initWithCString: "NSWeekDayNameArray"]; + NSWillBecomeMultiThreadedNotification + = [[NSString alloc] initWithCString: + "NSWillBecomeMultiThreadedNotification"]; + NSYearMonthWeekDesignations + = [[NSString alloc] initWithCString: "NSYearMonthWeekDesignations"]; + PortBecameInvalidNotification + = [[NSString alloc] initWithCString: "PortBecameInvalidNotification"]; + StreamException + = [[NSString alloc] initWithCString: "StreamException"]; + } +} + + /* Standard MapTable callbacks */ diff --git a/Testing/client.m b/Testing/client.m index e8b9ccc4f..8551f5e5a 100644 --- a/Testing/client.m +++ b/Testing/client.m @@ -175,6 +175,21 @@ printf("oneway %d\n", _F_ONEWAY); printf("%s - %s\n", [k cString], [[v description] cString]); } + { + NSDate *d = [NSDate date]; + + [NSConnection setDebug: 0]; + [NSDistantObject setDebug: 0]; + [NSPort setDebug: 0]; + for (j = 0; j < 10000; j++) + { + [p echoObject: localObj]; + } + + NSLog(@"Delay is %f", [d timeIntervalSinceNow]); +exit(0); + } + [arp release]; arp = [NSAutoreleasePool new]; printf("%d\n", [c retainCount]); diff --git a/Testing/server.h b/Testing/server.h index 8028137fe..343d6ffe9 100644 --- a/Testing/server.h +++ b/Testing/server.h @@ -51,6 +51,7 @@ struct myarray { : (int)i7 : (int)i8 : (int)i9 : (int)i10 : (int)i11 : (int)i12; - (float) returnFloat; - (double) returnDouble; +- (id) echoObject: (id)obj; @end #if NeXT_runtime diff --git a/Testing/server.m b/Testing/server.m index 9b2cc3a3f..512c2d585 100644 --- a/Testing/server.m +++ b/Testing/server.m @@ -79,6 +79,16 @@ return self; } +- (id) echoObject: (id)obj +{ + static BOOL debugging = YES; + + if (debugging) + { + [BinaryCStream setDebugging:NO]; + } + return obj; +} - (void) outputStats:obj { id c = [obj connectionForProxy];