This repository was archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
[System.Globalization.Native] Fix regressions from #22378 and #22390 #24085
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <stdlib.h> | ||
| #include <stdint.h> | ||
|
|
||
| static void *pal_allocarray(size_t numMembers, size_t count) | ||
| { | ||
| if (numMembers == 0 || count == 0) | ||
| return NULL; | ||
| if (SIZE_MAX / numMembers < count) | ||
| return NULL; | ||
| return malloc(numMembers * count); | ||
| } | ||
|
|
||
| static void *pal_reallocarray(void *ptr, size_t numMembers, size_t count) | ||
| { | ||
| if (numMembers == 0 || count == 0) | ||
| return NULL; | ||
| if (SIZE_MAX / numMembers < count) | ||
| return NULL; | ||
| return realloc(ptr, numMembers * count); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
| #include <search.h> | ||
| #include <string.h> | ||
|
|
||
| #include "pal_alloc.h" | ||
| #include "pal_collation.h" | ||
|
|
||
| c_static_assert_msg(UCOL_EQUAL == 0, "managed side requires 0 for equal strings"); | ||
|
|
@@ -142,8 +143,12 @@ static int AddItem(UCharList* list, const UChar item) | |
| size_t size = list->size++; | ||
| if (size >= list->capacity) | ||
| { | ||
| list->capacity *= 2; | ||
| UChar* ptr = (UChar*)realloc(list->items, list->capacity * sizeof(UChar*)); | ||
| list->capacity += 512; | ||
| if (list->capacity < size) | ||
| { | ||
| return FALSE; | ||
| } | ||
| UChar* ptr = (UChar*)pal_reallocarray(list->items, list->capacity, sizeof(UChar)); | ||
| if (ptr == NULL) | ||
| { | ||
| return FALSE; | ||
|
|
@@ -188,15 +193,14 @@ static UCharList* GetCustomRules(int32_t options, UColAttributeValue strength, i | |
| // Use 512 as the starting size, so the customRules won't have to grow if we are just | ||
| // doing the KanaType custom rule. | ||
| customRules->capacity = 512; | ||
| customRules->items = calloc(customRules->capacity, sizeof(UChar)); | ||
| customRules->size = 0; | ||
| customRules->items = pal_allocarray(customRules->capacity, sizeof(UChar)); | ||
| if (customRules->items == NULL) | ||
| { | ||
| free(customRules); | ||
| return NULL; | ||
| } | ||
|
|
||
| customRules->size = 0; | ||
|
|
||
| if (needsIgnoreKanaTypeCustomRule || needsNotIgnoreKanaTypeCustomRule) | ||
| { | ||
| UChar compareChar = needsIgnoreKanaTypeCustomRule ? '=' : '<'; | ||
|
|
@@ -280,7 +284,7 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, | |
|
|
||
| UCollator* pClonedCollator; | ||
| UCharList* customRules = GetCustomRules(options, strength, isIgnoreSymbols); | ||
| if (customRules == NULL) | ||
| if (customRules == NULL || customRules->size == 0) | ||
| { | ||
| pClonedCollator = ucol_safeClone(pCollator, NULL, NULL, pErr); | ||
| } | ||
|
|
@@ -292,7 +296,7 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, | |
| const UChar* localeRules = ucol_getRules(pCollator, &localeRulesLength); | ||
| int32_t completeRulesLength = localeRulesLength + customRuleLength + 1; | ||
|
|
||
| UChar* completeRules = calloc(completeRulesLength, sizeof(UChar)); | ||
| UChar* completeRules = pal_allocarray(completeRulesLength, sizeof(UChar)); | ||
|
|
||
| for (int i = 0; i < localeRulesLength; i++) | ||
| { | ||
|
|
@@ -302,11 +306,12 @@ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, | |
| { | ||
| completeRules[localeRulesLength + i] = customRules->items[i]; | ||
| } | ||
| completeRules[completeRulesLength - 1] = 0; | ||
|
|
||
| pClonedCollator = ucol_openRules(completeRules, completeRulesLength, UCOL_DEFAULT, strength, NULL, pErr); | ||
| free(completeRules); | ||
| free(customRules); | ||
| } | ||
| free(customRules); | ||
|
|
||
| if (isIgnoreSymbols) | ||
| { | ||
|
|
@@ -439,11 +444,15 @@ const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t opti | |
|
|
||
| TCollatorMap* map = (TCollatorMap*)malloc(sizeof(TCollatorMap)); | ||
| map->key = options; | ||
| void* entry = tsearch(map, &pSortHandle->collatorsPerOptionRoot, TreeComparer); | ||
| if ((*(TCollatorMap**)entry) == map) | ||
| // tfind on glibc is significantly faster than tsearch and we expect | ||
| // to hit the cache here often so it's benefitial to prefer lookup time | ||
| // over addition time | ||
| void* entry = tfind(map, &pSortHandle->collatorsPerOptionRoot, TreeComparer); | ||
| if (entry == NULL) | ||
| { | ||
| pCollator = CloneCollatorWithOptions(pSortHandle->regular, options, pErr); | ||
| map->UCollator = pCollator; | ||
| tsearch(map, &pSortHandle->collatorsPerOptionRoot, TreeComparer); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we separate out the regression fix into its own PR?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure |
||
| } | ||
| else | ||
| { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR is making a handful of unrelated improvements with the goal of improving perf... can you share measurements that demonstrate they move things in a positive direction? I'm not clear on why this change to +512 instead of *2 is definitively better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The safety check I added is actually never going to get hit. GetCustomRules has upper bound on how many custom rules can get added, so realistically the only two cases that can happen is the default array size (512) or the next bigger one (1024 both before and after my change).
The maximum size at the moment is something around 860.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll revert it to *2 since it doesn't really matter.