GC constraint solving should be parallel
[WebKit-https.git] / Source / JavaScriptCore / API / JSMarkingConstraintPrivate.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "JSMarkingConstraintPrivate.h"
28
29 #include "APICast.h"
30 #include "JSCInlines.h"
31 #include "SimpleMarkingConstraint.h"
32
33 using namespace JSC;
34
35 namespace {
36
37 Atomic<unsigned> constraintCounter;
38
39 struct Marker : JSMarker {
40     SlotVisitor* visitor;
41 };
42
43 bool isMarked(JSMarkerRef, JSObjectRef objectRef)
44 {
45     if (!objectRef)
46         return true; // Null is an immortal object.
47     
48     return Heap::isMarked(toJS(objectRef));
49 }
50
51 void mark(JSMarkerRef markerRef, JSObjectRef objectRef)
52 {
53     if (!objectRef)
54         return;
55     
56     static_cast<Marker*>(markerRef)->visitor->appendHiddenUnbarriered(toJS(objectRef));
57 }
58
59 } // anonymous namespace
60
61 void JSContextGroupAddMarkingConstraint(JSContextGroupRef group, JSMarkingConstraint constraintCallback, void *userData)
62 {
63     VM& vm = *toJS(group);
64     JSLockHolder locker(vm);
65     
66     unsigned constraintIndex = constraintCounter.exchangeAdd(1);
67     
68     // This is a guess. The algorithm should be correct no matter what we pick. This means
69     // that we expect this constraint to mark things even during a stop-the-world full GC, but
70     // we don't expect it to be able to mark anything at the very start of a GC before anything
71     // else gets marked.
72     ConstraintVolatility volatility = ConstraintVolatility::GreyedByMarking;
73     
74     auto constraint = std::make_unique<SimpleMarkingConstraint>(
75         toCString("Amc", constraintIndex, "(", RawPointer(bitwise_cast<void*>(constraintCallback)), ")"),
76         toCString("API Marking Constraint #", constraintIndex, " (", RawPointer(bitwise_cast<void*>(constraintCallback)), ", ", RawPointer(userData), ")"),
77         [constraintCallback, userData]
78         (SlotVisitor& slotVisitor) {
79             Marker marker;
80             marker.IsMarked = isMarked;
81             marker.Mark = mark;
82             marker.visitor = &slotVisitor;
83             
84             constraintCallback(&marker, userData);
85         },
86         volatility,
87         ConstraintConcurrency::Sequential);
88     
89     vm.heap.addMarkingConstraint(WTFMove(constraint));
90 }