Ignore:
Timestamp:
Jun 23, 2021, 12:20:02 PM (4 years ago)
Author:
[email protected]
Message:

add/removeManagedReference:withOwner: should have autoreleasepools
https://bugs.webkit.org/show_bug.cgi?id=227308

Reviewed by Darin Adler.

Since these APIs create autoreleased objects as an implementation detail
but don't return any to the caller there's no indication such autoreleased
objects could be accumulating. Additionally, it's entirely reasonable to
call these methods in a loop an a large set of objects, which further
exacerbates the problem.

  • API/JSVirtualMachine.mm:

(-[JSVirtualMachine addManagedReference:withOwner:]):
(-[JSVirtualMachine removeManagedReference:withOwner:]):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSVirtualMachine.mm

    r278082 r279179  
    163163
    164164- (void)addManagedReference:(id)object withOwner:(id)owner
    165 {   
    166     if ([object isKindOfClass:[JSManagedValue class]])
    167         [object didAddOwner:owner];
    168        
    169     object = getInternalObjcObject(object);
    170     owner = getInternalObjcObject(owner);
    171    
    172     if (!object || !owner)
    173         return;
    174    
    175     JSC::JSLockHolder locker(toJS(m_group));
    176     if ([self isOldExternalObject:owner] && ![self isOldExternalObject:object])
    177         [self addExternalRememberedObject:owner];
    178  
    179     Locker externalDataMutexLocker { m_externalDataMutex };
    180     RetainPtr<NSMapTable> ownedObjects = [m_externalObjectGraph objectForKey:owner];
    181     if (!ownedObjects) {
    182         NSPointerFunctionsOptions weakIDOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
    183         NSPointerFunctionsOptions integerOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
    184         ownedObjects = adoptNS([[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:integerOptions capacity:1]);
    185 
    186         [m_externalObjectGraph setObject:ownedObjects.get() forKey:owner];
    187     }
    188 
    189     size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects.get(), (__bridge void*)object));
    190     NSMapInsert(ownedObjects.get(), (__bridge void*)object, reinterpret_cast<void*>(count + 1));
     165{
     166    @autoreleasepool {
     167        if ([object isKindOfClass:[JSManagedValue class]])
     168            [object didAddOwner:owner];
     169
     170        object = getInternalObjcObject(object);
     171        owner = getInternalObjcObject(owner);
     172
     173        if (!object || !owner)
     174            return;
     175
     176        JSC::JSLockHolder locker(toJS(m_group));
     177        if ([self isOldExternalObject:owner] && ![self isOldExternalObject:object])
     178            [self addExternalRememberedObject:owner];
     179
     180        Locker externalDataMutexLocker { m_externalDataMutex };
     181        RetainPtr<NSMapTable> ownedObjects = [m_externalObjectGraph objectForKey:owner];
     182        if (!ownedObjects) {
     183            NSPointerFunctionsOptions weakIDOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
     184            NSPointerFunctionsOptions integerOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
     185            ownedObjects = adoptNS([[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:integerOptions capacity:1]);
     186
     187            [m_externalObjectGraph setObject:ownedObjects.get() forKey:owner];
     188        }
     189
     190        size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects.get(), (__bridge void*)object));
     191        NSMapInsert(ownedObjects.get(), (__bridge void*)object, reinterpret_cast<void*>(count + 1));
     192    }
    191193}
    192194
    193195- (void)removeManagedReference:(id)object withOwner:(id)owner
    194196{
    195     if ([object isKindOfClass:[JSManagedValue class]])
    196         [object didRemoveOwner:owner];
    197 
    198     object = getInternalObjcObject(object);
    199     owner = getInternalObjcObject(owner);
    200    
    201     if (!object || !owner)
    202         return;
    203    
    204     JSC::JSLockHolder locker(toJS(m_group));
    205    
    206     Locker externalDataMutexLocker { m_externalDataMutex };
    207     NSMapTable *ownedObjects = [m_externalObjectGraph objectForKey:owner];
    208     if (!ownedObjects)
    209         return;
    210    
    211     size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects, (__bridge void*)object));
    212     if (count > 1) {
    213         NSMapInsert(ownedObjects, (__bridge void*)object, reinterpret_cast<void*>(count - 1));
    214         return;
    215     }
    216    
    217     if (count == 1)
    218         NSMapRemove(ownedObjects, (__bridge void*)object);
    219 
    220     if (![ownedObjects count]) {
    221         [m_externalObjectGraph removeObjectForKey:owner];
    222         [m_externalRememberedSet removeObjectForKey:owner];
     197    @autoreleasepool {
     198        if ([object isKindOfClass:[JSManagedValue class]])
     199            [object didRemoveOwner:owner];
     200
     201        object = getInternalObjcObject(object);
     202        owner = getInternalObjcObject(owner);
     203
     204        if (!object || !owner)
     205            return;
     206
     207        JSC::JSLockHolder locker(toJS(m_group));
     208
     209        Locker externalDataMutexLocker { m_externalDataMutex };
     210        NSMapTable *ownedObjects = [m_externalObjectGraph objectForKey:owner];
     211        if (!ownedObjects)
     212            return;
     213
     214        size_t count = reinterpret_cast<size_t>(NSMapGet(ownedObjects, (__bridge void*)object));
     215        if (count > 1) {
     216            NSMapInsert(ownedObjects, (__bridge void*)object, reinterpret_cast<void*>(count - 1));
     217            return;
     218        }
     219
     220        if (count == 1)
     221            NSMapRemove(ownedObjects, (__bridge void*)object);
     222
     223        if (![ownedObjects count]) {
     224            [m_externalObjectGraph removeObjectForKey:owner];
     225            [m_externalRememberedSet removeObjectForKey:owner];
     226        }
    223227    }
    224228}
Note: See TracChangeset for help on using the changeset viewer.