Changeset 6f7aff3
- Timestamp:
- Oct 19, 2021, 10:31:53 AM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
- Children:
- fe18b46
- Parents:
- 7b0e8b7
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/containers/string_res.cfa
r7b0e8b7 r6f7aff3 53 53 static inline int ByteCmp( char *, int, int, char *, int, int ); // compare 2 blocks of bytes 54 54 static inline char *VbyteAlloc( VbyteHeap &, int ); // allocate a block bytes in the heap 55 55 static inline char *VbyteTryAdjustLast( VbyteHeap &, int ); 56 56 57 57 static inline void AddThisAfter( HandleNode &, HandleNode & ); … … 313 313 this.Handle.s = resultSesStart + beforeLen; 314 314 this.Handle.lnth = bsize; 315 MoveThisAfter( this.Handle, *resultPadPosition ); 315 if (resultPadPosition) 316 MoveThisAfter( this.Handle, *resultPadPosition ); 316 317 317 318 // adjust all substring string and handle locations, and check if any substring strings are outside the new base string … … 365 366 } 366 367 } 367 MoveThisAfter( p->Handle, *resultPadPosition ); // move substring handle to maintain sorted order by string position 368 if (resultPadPosition) 369 MoveThisAfter( p->Handle, *resultPadPosition ); // move substring handle to maintain sorted order by string position 368 370 } 369 371 } … … 387 389 verify( editSetLength >= this.Handle.lnth ); 388 390 389 390 if ( this.Handle.lnth == editSetLength // the entire run of the share-edit set is being overwritten: SES's result will only use characters from the source string 391 && & valSrc // sourcing from a managed string 392 && valSrc.Handle.ulink == this.Handle.ulink ) { // sourcing from same heap 393 391 if ( this.shareEditSet_owns_ulink ) { // assigning to private context 392 // ok to overwrite old value within LHS 393 char * prefixStartOrig = shareEditSetStartPeer->Handle.s; 394 int prefixLen = this.Handle.s - prefixStartOrig; 395 char * suffixStartOrig = this.Handle.s + this.Handle.lnth; 396 int suffixLen = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - suffixStartOrig; 397 398 int delta = bsize - this.Handle.lnth; 399 if ( char * oldBytes = VbyteTryAdjustLast( *this.Handle.ulink, delta ) ) { 400 // growing: copy from old to new 401 char * dest = VbyteAlloc( *this.Handle.ulink, editSetLength ); 402 char *destCursor = dest; memcpy(destCursor, prefixStartOrig, prefixLen); 403 destCursor += prefixLen; memcpy(destCursor, buffer , bsize ); 404 destCursor += this.Handle.lnth; memcpy(destCursor, suffixStartOrig, suffixLen); 405 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 406 dest, 407 editSetLength, 408 0p, bsize); 409 free( oldBytes ); 410 } else { 411 // room is already allocated in-place: bubble suffix and overwite middle 412 memmove( suffixStartOrig + delta, suffixStartOrig, suffixLen ); 413 memcpy( this.Handle.s, buffer, bsize ); 414 415 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 416 shareEditSetStartPeer->Handle.s, 417 editSetLength, 418 0p, bsize); 419 } 420 421 } else if ( // assigning to shared context 422 this.Handle.lnth == editSetLength && // overwriting entire run of SES 423 & valSrc && // sourcing from a managed string 424 valSrc.Handle.ulink == this.Handle.ulink ) { // sourcing from same heap 425 426 // SES's result will only use characters from the source string => reuse source 394 427 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 395 428 valSrc.Handle.s, … … 398 431 399 432 } else { 433 // overwriting a proper substring of some string: mash characters from old and new together (copy on write) 434 // OR we are importing characters: need to copy eagerly (can't refer to source) 400 435 401 436 // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer … … 416 451 } 417 452 418 // we are only overwriting a proper substring of some string: need to mash characters from old and new together419 // OR we are importing characters: need to copy eagerly420 453 string_res pasting = { 421 454 * this.Handle.ulink, // maintain same heap, regardless of context … … 439 472 &pasting.Handle, bsize); 440 473 } 441 442 // So now, capture their values for use in the overlap cases, below.443 // Do not factor these definitions with the arguments used in string building above.444 445 474 } 446 475 … … 750 779 751 780 // Allocates specified storage for a string from byte-string area. If not enough space remains to perform the 752 // allocation, the garbage collection routine is called and a second attempt is made to allocate the space. If the 753 // second attempt fails, a further attempt is made to create a new, larger byte-string area. 781 // allocation, the garbage collection routine is called. 754 782 755 783 static inline char * VbyteAlloc( VbyteHeap & this, int size ) with(this) { … … 775 803 return r; 776 804 } // VbyteAlloc 805 806 807 // Adjusts the last allocation in this heap by delta bytes, or resets this heap to be able to offer 808 // new allocations of its original size + delta bytes. Positive delta means bigger; 809 // negative means smaller. A null return indicates that the original heap location has room for 810 // the requested growth. A non-null return indicates that copying to a new location is required 811 // but has not been done; the returned value is the old heap storage location; `this` heap is 812 // modified to reference the new location. In the copy-requred case, the caller should use 813 // VbyteAlloc to claim the new space, while doing optimal copying from old to new, then free old. 814 815 static inline char * VbyteTryAdjustLast( VbyteHeap & this, int delta ) with(this) { 816 817 if ( ( uintptr_t )EndVbyte + delta <= ( uintptr_t )ExtVbyte ) { 818 // room available 819 EndVbyte += delta; 820 return 0p; 821 } 822 823 char *oldBytes = StartVbyte; 824 825 NoOfExtensions += 1; 826 CurrSize *= 2; 827 StartVbyte = EndVbyte = alloc(CurrSize); 828 ExtVbyte = StartVbyte + CurrSize; 829 830 return oldBytes; 831 } 777 832 778 833 -
tests/collections/string-api-coverage.cfa
r7b0e8b7 r6f7aff3 1 1 #include <containers/string.hfa> 2 #include <string_sharectx.hfa> 2 3 3 4 void assertWellFormedHandleList( int maxLen ) { // with(HeapArea) … … 25 26 26 27 int main () { 28 29 #ifdef STRING_SHARING_OFF 30 sout | "string sharing disabled"; 31 string_sharectx c = { NO_SHARING }; 32 #endif 33 27 34 string s = "hello"; 28 35 string s2 = "hello"; -
tests/collections/string-ctx-manage.cfa
r7b0e8b7 r6f7aff3 3 3 #include <string_res.hfa> 4 4 5 // In these tests, shared heaps are never remotely full and string sizes are tiny. 6 // So here, the SUT should put a yes-sharing string in a heap with lots of spare room. 7 // The SUT should always keep a no-sharing string's buffer 1x--2x the string's size. 8 // This check uses 3x as a heuristic split between those cases. 9 void assertSpareRoomInHeap( string & s, bool expectOversized ) { 10 double bytesInHeap = DEBUG_string_bytes_in_heap(s.inner->Handle.ulink); 11 double bytesUsed = s.inner->Handle.lnth; 12 double overhead = bytesInHeap / bytesUsed; 13 assert (overhead >= 1); 14 if ( expectOversized ) 15 assert( overhead >= 3.0 ); 16 else 17 assert( overhead < 3.0 ); 18 } 19 5 20 void baseline() { 6 21 string x = "hi"; 22 assertSpareRoomInHeap( x, true ); 7 23 8 24 string y = x; // construct y in same context, no write yet => no copy yet 25 assertSpareRoomInHeap( y, true ); 9 26 assert( y.inner->Handle.s == x.inner->Handle.s); 10 27 sout | y; // hi 11 28 12 29 x = "bye"; 30 assertSpareRoomInHeap( x, true ); 13 31 y = x; // y in same context, no write yet => no copy yet 32 assertSpareRoomInHeap( y, true ); 14 33 assert( y.inner->Handle.s == x.inner->Handle.s); 15 34 sout | y; // bye … … 18 37 void eagerCopy() { 19 38 string x = "hi"; 39 assertSpareRoomInHeap( x, true ); 20 40 string_sharectx c = { NEW_SHARING }; 21 41 22 42 string y = x; // construct y in different context => eager copy 43 assertSpareRoomInHeap( y, true ); 23 44 assert( y.inner->Handle.s != x.inner->Handle.s); 24 45 sout | y; // hi 25 46 26 47 x = "bye"; 48 assertSpareRoomInHeap( x, true ); 27 49 y = x; // y was already in different context => eager copy 50 assertSpareRoomInHeap( y, true ); 28 51 assert( y.inner->Handle.s != x.inner->Handle.s); 29 52 sout | y; // bye … … 32 55 void soloAlloc() { 33 56 string x = "hi"; 57 assertSpareRoomInHeap( x, true ); 34 58 string_sharectx c = { NO_SHARING }; 35 59 36 60 string y = x; // y allocates into private pad, implying eager copy 61 assertSpareRoomInHeap( y, false ); 37 62 assert( y.inner->Handle.s != x.inner->Handle.s); 38 assert( DEBUG_string_bytes_in_heap(y.inner->Handle.ulink) == y.inner->Handle.lnth ); // y is in a perfectly fitting heap39 63 sout | y; // hi 40 64 41 65 x = "bye"; 66 assertSpareRoomInHeap( x, true ); 42 67 y = x; // into private y => eager copy 68 assertSpareRoomInHeap( y, false ); 43 69 assert( y.inner->Handle.s != x.inner->Handle.s); 44 // assert( DEBUG_string_bytes_in_heap(y.inner->Handle.ulink) == y.inner->Handle.lnth ); // optimization required45 70 sout | y; // bye 46 71 }
Note: See TracChangeset
for help on using the changeset viewer.