17074e4ca6f9559a968d18e4ffa161f80ee8f6b8
[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 "MarkingConstraint.h"
32 #include "VisitingTimeout.h"
33
34 using namespace JSC;
35
36 namespace {
37
38 Atomic<unsigned> constraintCounter;
39
40 struct Marker : JSMarker {
41     SlotVisitor* visitor;
42 };
43
44 bool isMarked(JSMarkerRef, JSObjectRef objectRef)
45 {
46     if (!objectRef)
47         return true; // Null is an immortal object.
48     
49     return Heap::isMarked(toJS(objectRef));
50 }
51
52 void mark(JSMarkerRef markerRef, JSObjectRef objectRef)
53 {
54     if (!objectRef)
55         return;
56     
57     static_cast<Marker*>(markerRef)->visitor->appendHiddenUnbarriered(toJS(objectRef));
58 }
59
60 } // anonymous namespace
61
62 void JSContextGroupAddMarkingConstraint(JSContextGroupRef group, JSMarkingConstraint constraintCallback, void *userData)
63 {
64     VM& vm = *toJS(group);
65     JSLockHolder locker(vm);
66     
67     unsigned constraintIndex = constraintCounter.exchangeAdd(1);
68     
69     // This is a guess. The algorithm should be correct no matter what we pick. This means
70     // that we expect this constraint to mark things even during a stop-the-world full GC, but
71     // we don't expect it to be able to mark anything at the very start of a GC before anything
72     // else gets marked.
73     ConstraintVolatility volatility = ConstraintVolatility::GreyedByMarking;
74     
75     auto constraint = std::make_unique<MarkingConstraint>(
76         toCString("Amc", constraintIndex, "(", RawPointer(bitwise_cast<void*>(constraintCallback)), ")"),
77         toCString("API Marking Constraint #", constraintIndex, " (", RawPointer(bitwise_cast<void*>(constraintCallback)), ", ", RawPointer(userData), ")"),
78         [constraintCallback, userData]
79         (SlotVisitor& slotVisitor, const VisitingTimeout&) {
80             Marker marker;
81             marker.IsMarked = isMarked;
82             marker.Mark = mark;
83             marker.visitor = &slotVisitor;
84             
85             constraintCallback(&marker, userData);
86         },
87         volatility);
88     
89     vm.heap.addMarkingConstraint(WTFMove(constraint));
90 }