Ignore:
Timestamp:
Apr 15, 2014, 2:05:09 PM (11 years ago)
Author:
[email protected]
Message:

Objective-C API external object graphs don't handle generational collection properly
https://bugs.webkit.org/show_bug.cgi?id=131634

Reviewed by Geoffrey Garen.

If the set of Objective-C objects transitively reachable through an object changes, we
need to update the set of opaque roots accordingly. If we don't, the next EdenCollection
won't rescan the external object graph, which would lead us to consider a newly allocated
JSManagedValue to be dead.

  • API/JSBase.cpp:

(JSSynchronousEdenCollectForDebugging):

  • API/JSVirtualMachine.mm:

(-[JSVirtualMachine initWithContextGroupRef:]):
(-[JSVirtualMachine dealloc]):
(-[JSVirtualMachine isOldExternalObject:]):
(-[JSVirtualMachine addExternalRememberedObject:]):
(-[JSVirtualMachine addManagedReference:withOwner:]):
(-[JSVirtualMachine removeManagedReference:withOwner:]):
(-[JSVirtualMachine externalRememberedSet]):
(scanExternalObjectGraph):
(scanExternalRememberedSet):

  • API/JSVirtualMachineInternal.h:
  • API/tests/testapi.mm:
  • heap/Heap.cpp:

(JSC::Heap::markRoots):

  • heap/Heap.h:

(JSC::Heap::slotVisitor):

  • heap/SlotVisitor.h:
  • heap/SlotVisitorInlines.h:

(JSC::SlotVisitor::containsOpaqueRoot):
(JSC::SlotVisitor::containsOpaqueRootTriState):

File:
1 edited

Legend:

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

    r166835 r167326  
    8888    NSMapTable *m_contextCache;
    8989    NSMapTable *m_externalObjectGraph;
     90    NSMapTable *m_externalRememberedSet;
    9091}
    9192
     
    114115    NSPointerFunctionsOptions strongIDOptions = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality;
    115116    m_externalObjectGraph = [[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:strongIDOptions capacity:0];
     117
     118    NSPointerFunctionsOptions integerOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
     119    m_externalRememberedSet = [[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:integerOptions capacity:0];
    116120   
    117121    [JSVMWrapperCache addWrapper:self forJSContextGroupRef:group];
     
    125129    [m_contextCache release];
    126130    [m_externalObjectGraph release];
     131    [m_externalRememberedSet release];
    127132    [super dealloc];
    128133}
     
    144149
    145150    return object;
     151}
     152
     153- (bool)isOldExternalObject:(id)object
     154{
     155    JSC::VM* vm = toJS(m_group);
     156    return vm->heap.slotVisitor().containsOpaqueRoot(object);
     157}
     158
     159- (void)addExternalRememberedObject:(id)object
     160{
     161    ASSERT([self isOldExternalObject:object]);
     162    [m_externalRememberedSet setObject:[NSNumber numberWithBool:true] forKey:object];
    146163}
    147164
     
    158175   
    159176    JSC::JSLockHolder locker(toJS(m_group));
    160    
     177    if ([self isOldExternalObject:owner] && ![self isOldExternalObject:object])
     178        [self addExternalRememberedObject:owner];
     179 
    161180    NSMapTable *ownedObjects = [m_externalObjectGraph objectForKey:owner];
    162181    if (!ownedObjects) {
     
    199218        NSMapRemove(ownedObjects, object);
    200219
    201     if (![ownedObjects count])
     220    if (![ownedObjects count]) {
    202221        [m_externalObjectGraph removeObjectForKey:owner];
     222        [m_externalRememberedSet removeObjectForKey:owner];
     223    }
    203224}
    204225
     
    233254{
    234255    return m_externalObjectGraph;
     256}
     257
     258- (NSMapTable *)externalRememberedSet
     259{
     260    return m_externalRememberedSet;
    235261}
    236262
     
    254280           
    255281            NSMapTable *ownedObjects = [externalObjectGraph objectForKey:static_cast<id>(nextRoot)];
    256             id ownedObject;
    257             NSEnumerator *enumerator = [ownedObjects keyEnumerator];
    258             while ((ownedObject = [enumerator nextObject]))
     282            for (id ownedObject in ownedObjects)
    259283                stack.append(static_cast<void*>(ownedObject));
    260284        }
     
    262286}
    263287
    264 #endif
    265 
     288void scanExternalRememberedSet(JSC::VM& vm, JSC::SlotVisitor& visitor)
     289{
     290    @autoreleasepool {
     291        JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)];
     292        if (!virtualMachine)
     293            return;
     294        NSMapTable *externalObjectGraph = [virtualMachine externalObjectGraph];
     295        NSMapTable *externalRememberedSet = [virtualMachine externalRememberedSet];
     296        for (id key in externalRememberedSet) {
     297            NSMapTable *ownedObjects = [externalObjectGraph objectForKey:key];
     298            for (id ownedObject in ownedObjects)
     299                scanExternalObjectGraph(vm, visitor, ownedObject);
     300        }
     301        [externalRememberedSet removeAllObjects];
     302    }
     303}
     304
     305#endif // JSC_OBJC_API_ENABLED
Note: See TracChangeset for help on using the changeset viewer.