Bug 205086 - Worklist::deleteCancelledPlansForVM() should not assume that a cancelled plan is ready for deletion.
Summary: Worklist::deleteCancelledPlansForVM() should not assume that a cancelled plan...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Mark Lam
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2019-12-10 14:49 PST by Mark Lam
Modified: 2019-12-10 17:45 PST (History)
6 users (show)

See Also:


Attachments
proposed patch. (3.92 KB, patch)
2019-12-10 16:57 PST, Mark Lam
saam: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Lam 2019-12-10 14:49:38 PST
Another thread may still have a reference to the cancelled plan and hasn't released it yet.

<rdar://problem/57795002>
Comment 1 Mark Lam 2019-12-10 16:57:34 PST
Created attachment 385319 [details]
proposed patch.
Comment 2 Saam Barati 2019-12-10 17:02:01 PST
Comment on attachment 385319 [details]
proposed patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=385319&action=review

> Source/JavaScriptCore/dfg/DFGWorklist.cpp:310
>      HashSet<RefPtr<Plan>> removedPlans;

this shouldn't be a HashSet, right?

> Source/JavaScriptCore/dfg/DFGWorklist.cpp:318
> +        removedPlans.add(WTFMove(plan));

isn't this easier to just append only when ref count is 1?

like:
Plan* plan = m_cancelledPlansPendingDestruction[I].get();
if (plan->refCount() == 1) removedPlans.append(...)

and remove the +1 ref in the above code
Comment 3 Mark Lam 2019-12-10 17:05:43 PST
Comment on attachment 385319 [details]
proposed patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=385319&action=review

>> Source/JavaScriptCore/dfg/DFGWorklist.cpp:310
>>      HashSet<RefPtr<Plan>> removedPlans;
> 
> this shouldn't be a HashSet, right?

This should be a HashSet because (as I explained offline previously for the original patch) there's a chance that the GC thread cancels the plan and appends it to m_cancelledPlansPendingDestruction, and then the compiler thread sees it and appends it to m_cancelledPlansPendingDestruction again before the mutator can iterate m_cancelledPlansPendingDestruction.  As a result, the same plan may show up in m_cancelledPlansPendingDestruction more than once, but we only want to add it to removedPlans once.

>> Source/JavaScriptCore/dfg/DFGWorklist.cpp:318
>> +        removedPlans.add(WTFMove(plan));
> 
> isn't this easier to just append only when ref count is 1?
> 
> like:
> Plan* plan = m_cancelledPlansPendingDestruction[I].get();
> if (plan->refCount() == 1) removedPlans.append(...)
> 
> and remove the +1 ref in the above code

Good point.  I will change the fix.
Comment 4 Mark Lam 2019-12-10 17:07:51 PST
Comment on attachment 385319 [details]
proposed patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=385319&action=review

>>> Source/JavaScriptCore/dfg/DFGWorklist.cpp:318
>>> +        removedPlans.add(WTFMove(plan));
>> 
>> isn't this easier to just append only when ref count is 1?
>> 
>> like:
>> Plan* plan = m_cancelledPlansPendingDestruction[I].get();
>> if (plan->refCount() == 1) removedPlans.append(...)
>> 
>> and remove the +1 ref in the above code
> 
> Good point.  I will change the fix.

I take this back.  Because the plan can appear in m_cancelledPlansPendingDestruction more than once, this scheme won't work.  We have to filter it through the HashSet.
Comment 5 Saam Barati 2019-12-10 17:34:42 PST
Comment on attachment 385319 [details]
proposed patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=385319&action=review

> Source/JavaScriptCore/dfg/DFGWorklist.cpp:323
>          RELEASE_ASSERT(plan->stage() == Plan::Cancelled);

should we make this a debug assert like before?
Comment 6 Mark Lam 2019-12-10 17:42:37 PST
(In reply to Saam Barati from comment #5)
> Comment on attachment 385319 [details]
> proposed patch.
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=385319&action=review
> 
> > Source/JavaScriptCore/dfg/DFGWorklist.cpp:323
> >          RELEASE_ASSERT(plan->stage() == Plan::Cancelled);
> 
> should we make this a debug assert like before?

I'll change this to a debug assert.  I also added a comment explaining how we can have the same cancelled plan appear more than once in m_cancelledPlansPendingDestruction, and why we need to filter it through the HashSet.  The fact that you asked about it shows that we'll probably forget about this detail in the future.  Hence, a comment is needed to document it for posterity.
Comment 7 Mark Lam 2019-12-10 17:45:39 PST
Thanks for the review.  Landed in r253358: <http://trac.webkit.org/r253358>.