2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include <wtf/RefCounted.h>
30 #include <wtf/SentinelLinkedList.h>
34 class Watchpoint
: public BasicRawSentinelNode
<Watchpoint
> {
40 virtual ~Watchpoint();
42 void fire() { fireInternal(); }
45 virtual void fireInternal() = 0;
48 enum InitialWatchpointSetMode
{ InitializedWatching
, InitializedBlind
};
50 class InlineWatchpointSet
;
52 class WatchpointSet
: public RefCounted
<WatchpointSet
> {
54 WatchpointSet(InitialWatchpointSetMode
);
57 bool isStillValid() const { return !m_isInvalidated
; }
58 bool hasBeenInvalidated() const { return m_isInvalidated
; }
60 // As a convenience, this will ignore 0. That's because code paths in the DFG
61 // that create speculation watchpoints may choose to bail out if speculation
62 // had already been terminated.
63 void add(Watchpoint
*);
65 // Force the watchpoint set to behave as if it was being watched even if no
66 // watchpoints have been installed. This will result in invalidation if the
67 // watchpoint would have fired. That's a pretty good indication that you
68 // probably don't want to set watchpoints, since we typically don't want to
69 // set watchpoints that we believe will actually be fired.
70 void startWatching() { m_isWatched
= true; }
79 bool* addressOfIsWatched() { return &m_isWatched
; }
81 JS_EXPORT_PRIVATE
void notifyWriteSlow(); // Call only if you've checked isWatched.
84 void fireAllWatchpoints();
86 friend class InlineWatchpointSet
;
88 SentinelLinkedList
<Watchpoint
, BasicRawSentinelNode
<Watchpoint
> > m_set
;
93 // InlineWatchpointSet is a low-overhead, non-copyable watchpoint set in which
94 // it is not possible to quickly query whether it is being watched in a single
95 // branch. There is a fairly simple tradeoff between WatchpointSet and
96 // InlineWatchpointSet:
98 // Do you have to emit JIT code that rapidly tests whether the watchpoint set
99 // is being watched? If so, use WatchpointSet.
101 // Do you need multiple parties to have pointers to the same WatchpointSet?
102 // If so, use WatchpointSet.
104 // Do you have to allocate a lot of watchpoint sets? If so, use
105 // InlineWatchpointSet unless you answered "yes" to the previous questions.
107 // InlineWatchpointSet will use just one pointer-width word of memory unless
108 // you actually add watchpoints to it, in which case it internally inflates
109 // to a pointer to a WatchpointSet, and transfers its state to the
112 class InlineWatchpointSet
{
113 WTF_MAKE_NONCOPYABLE(InlineWatchpointSet
);
115 InlineWatchpointSet(InitialWatchpointSetMode mode
)
116 : m_data((mode
== InitializedWatching
? IsWatchedFlag
: 0) | IsThinFlag
)
120 ~InlineWatchpointSet()
127 bool hasBeenInvalidated() const
130 return fat()->hasBeenInvalidated();
131 return m_data
& IsInvalidatedFlag
;
134 bool isStillValid() const
136 return !hasBeenInvalidated();
139 void add(Watchpoint
*);
144 fat()->startWatching();
147 m_data
|= IsWatchedFlag
;
153 fat()->notifyWrite();
156 if (!(m_data
& IsWatchedFlag
))
158 m_data
|= IsInvalidatedFlag
;
162 static const uintptr_t IsThinFlag
= 1;
163 static const uintptr_t IsInvalidatedFlag
= 2;
164 static const uintptr_t IsWatchedFlag
= 4;
166 bool isThin() const { return m_data
& IsThinFlag
; }
167 bool isFat() const { return !isThin(); };
172 return bitwise_cast
<WatchpointSet
*>(m_data
);
175 const WatchpointSet
* fat() const
178 return bitwise_cast
<WatchpointSet
*>(m_data
);
181 WatchpointSet
* inflate()
185 return inflateSlow();
188 JS_EXPORT_PRIVATE WatchpointSet
* inflateSlow();
189 JS_EXPORT_PRIVATE
void freeFat();
196 #endif // Watchpoint_h