Changeset 280668 in webkit


Ignore:
Timestamp:
Aug 4, 2021 3:53:54 PM (3 years ago)
Author:
fpizlo@apple.com
Message:

[libpas] medium size class lookup needs to correctly fence the counting lock read path
https://bugs.webkit.org/show_bug.cgi?id=228799

Reviewed by Tadeu Zagallo.

The medium size class lookup does a binary search on a data structure that may mutate; we
catch that using a counting lock. But the algorithm wasn't fencing the tail end; it's supposed
to reread the count at the end but that read was not fenced.

This adds the fencing using pas_depend. I confirmed that the disassembly does the right thing.
It adds very little code.

Also rebased a test. Libpas tests are very specific about memory usage in some cases, and so
sometimes you will encounter a test run that requires limits to be adjusted. This happens
because some tests can sometimes create very complex heap layouts that really do use more
memory than we asserted, but the assertion had always worked because the test never ran with
the "wrong" kind of layout. This fixes a one-off test failure I saw when debugging this fix.

  • libpas/src/libpas/pas_mutation_count.h:

(pas_mutation_count_matches_with_dependency):
(pas_mutation_count_matches): Deleted.

  • libpas/src/libpas/pas_segregated_heap.c:

(medium_directory_tuple_for_index_impl):
(medium_directory_tuple_for_index_with_lock):
(pas_segregated_heap_medium_directory_tuple_for_index):

  • libpas/src/test/ThingyAndUtilityHeapAllocationTests.cpp:

(std::addLargeHeapTests):

Location:
trunk/Source/bmalloc
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/bmalloc/ChangeLog

    r280605 r280668  
     12021-08-04  Filip Pizlo  <fpizlo@apple.com>
     2
     3        [libpas] medium size class lookup needs to correctly fence the counting lock read path
     4        https://bugs.webkit.org/show_bug.cgi?id=228799
     5
     6        Reviewed by Tadeu Zagallo.
     7
     8        The medium size class lookup does a binary search on a data structure that may mutate; we
     9        catch that using a counting lock. But the algorithm wasn't fencing the tail end; it's supposed
     10        to reread the count at the end but that read was not fenced.
     11
     12        This adds the fencing using pas_depend. I confirmed that the disassembly does the right thing.
     13        It adds very little code.
     14
     15        Also rebased a test. Libpas tests are very specific about memory usage in some cases, and so
     16        sometimes you will encounter a test run that requires limits to be adjusted. This happens
     17        because some tests can sometimes create very complex heap layouts that really do use more
     18        memory than we asserted, but the assertion had always worked because the test never ran with
     19        the "wrong" kind of layout. This fixes a one-off test failure I saw when debugging this fix.
     20
     21        * libpas/src/libpas/pas_mutation_count.h:
     22        (pas_mutation_count_matches_with_dependency):
     23        (pas_mutation_count_matches): Deleted.
     24        * libpas/src/libpas/pas_segregated_heap.c:
     25        (medium_directory_tuple_for_index_impl):
     26        (medium_directory_tuple_for_index_with_lock):
     27        (pas_segregated_heap_medium_directory_tuple_for_index):
     28        * libpas/src/test/ThingyAndUtilityHeapAllocationTests.cpp:
     29        (std::addLargeHeapTests):
     30
    1312021-08-03  Filip Pizlo  <fpizlo@apple.com>
    232
  • trunk/Source/bmalloc/libpas/src/libpas/pas_mutation_count.h

    r279867 r280668  
    6767}
    6868
    69 static inline bool pas_mutation_count_matches(pas_mutation_count* mutation_count,
    70                                               pas_mutation_count saved_mutation_count)
     69static inline bool pas_mutation_count_matches_with_dependency(pas_mutation_count* mutation_count,
     70                                                              pas_mutation_count saved_mutation_count,
     71                                                              uintptr_t dependency)
    7172{
    7273    pas_compiler_fence();
    73     return mutation_count->count == saved_mutation_count.count;
     74    return mutation_count[pas_depend(dependency)].count == saved_mutation_count.count;
    7475}
    7576
  • trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_heap.c

    r279867 r280668  
    235235}
    236236
    237 static pas_segregated_heap_medium_directory_tuple*
     237typedef struct {
     238    pas_segregated_heap_medium_directory_tuple* tuple;
     239    uintptr_t dependency;
     240} medium_directory_tuple_for_index_impl_result;
     241
     242static PAS_ALWAYS_INLINE medium_directory_tuple_for_index_impl_result
    238243medium_directory_tuple_for_index_impl(
    239244    pas_segregated_heap_rare_data* rare_data,
     
    248253    unsigned end;
    249254    pas_segregated_heap_medium_directory_tuple* best;
     255    medium_directory_tuple_for_index_impl_result result;
    250256   
    251257    PAS_ASSERT(rare_data);
     
    257263    end = num_medium_directories;
    258264    best = NULL;
     265
     266    result.dependency = (uintptr_t)medium_directories;
    259267   
    260268    while (end > begin) {
    261269        unsigned middle;
    262270        pas_segregated_heap_medium_directory_tuple* directory;
     271        unsigned begin_index;
     272        unsigned end_index;
    263273
    264274        middle = (begin + end) >> 1;
     
    270280                    begin, end, middle, directory->begin_index, directory->end_index);
    271281        }
    272        
    273         if (index < directory->begin_index) {
     282
     283        begin_index = directory->begin_index;
     284        end_index = directory->end_index;
     285       
     286        result.dependency += begin_index + end_index;
     287       
     288        if (index < begin_index) {
    274289            end = middle;
    275290            best = directory;
     
    277292        }
    278293       
    279         if (index > directory->end_index) {
     294        if (index > end_index) {
    280295            begin = middle + 1;
    281296            continue;
    282297        }
    283        
    284         return directory;
     298
     299        result.tuple = directory;
     300        return result;
    285301    }
    286302
    287303    switch (search_mode) {
    288304    case pas_segregated_heap_medium_size_directory_search_within_size_class_progression:
    289         return NULL;
     305        result.tuple = NULL;
     306        return result;
    290307       
    291308    case pas_segregated_heap_medium_size_directory_search_least_greater_equal:
    292         return best;
     309        result.tuple = best;
     310        return result;
    293311    }
    294312
    295313    PAS_ASSERT(!"Should not be reached");
    296     return NULL;
     314    result.tuple = NULL;
     315    return result;
    297316}
    298317
     
    319338        rare_data->num_medium_directories,
    320339        index,
    321         search_mode);
     340        search_mode).tuple;
    322341   
    323342    pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
     
    337356    pas_segregated_heap_medium_directory_tuple* medium_directories;
    338357    unsigned num_medium_directories;
    339     pas_segregated_heap_medium_directory_tuple* result;
     358    medium_directory_tuple_for_index_impl_result result;
    340359   
    341360    rare_data = pas_segregated_heap_rare_data_ptr_load(&heap->rare_data);
     
    362381        rare_data, medium_directories, num_medium_directories, index, search_mode);
    363382   
    364     if (pas_mutation_count_matches(&rare_data->mutation_count, saved_count))
    365         return result;
     383    if (pas_mutation_count_matches_with_dependency(
     384            &rare_data->mutation_count, saved_count, result.dependency))
     385        return result.tuple;
    366386   
    367387    return medium_directory_tuple_for_index_with_lock(
  • trunk/Source/bmalloc/libpas/src/test/ThingyAndUtilityHeapAllocationTests.cpp

    r279867 r280668  
    27212721                                        AllocationProgram::free("secondHalf")));
    27222722    ADD_TEST(testComplexLargeAllocation(IsolatedComplexAllocator(7, 1),
    2723                                         ExpectedBytes::upperBound(417792),
     2723                                        ExpectedBytes::upperBound(638976),
    27242724                                        AllocationProgram::allocate("boot", 40960, 1),
    27252725                                        AllocationProgram::free("boot"),
Note: See TracChangeset for help on using the changeset viewer.