2 * Copyright (C) 2013 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.
26 #ifndef DFGDesiredWatchpoints_h
27 #define DFGDesiredWatchpoints_h
31 #include "CodeOrigin.h"
32 #include "DFGCommonData.h"
33 #include "JSArrayBufferView.h"
34 #include "Watchpoint.h"
35 #include <wtf/HashMap.h>
36 #include <wtf/HashSet.h>
37 #include <wtf/Noncopyable.h>
38 #include <wtf/Vector.h>
40 namespace JSC
{ namespace DFG
{
42 template<typename WatchpointSetType
>
43 struct WatchpointForGenericWatchpointSet
{
44 WatchpointForGenericWatchpointSet()
45 : m_exitKind(ExitKindUnset
)
50 WatchpointForGenericWatchpointSet(
51 CodeOrigin codeOrigin
, ExitKind exitKind
, WatchpointSetType
* set
)
52 : m_codeOrigin(codeOrigin
)
53 , m_exitKind(exitKind
)
58 CodeOrigin m_codeOrigin
;
60 WatchpointSetType
* m_set
;
64 struct GenericSetAdaptor
{
65 static void add(CodeBlock
*, T
* set
, Watchpoint
* watchpoint
)
67 return set
->add(watchpoint
);
69 static bool hasBeenInvalidated(T
* set
) { return set
->hasBeenInvalidated(); }
72 struct ArrayBufferViewWatchpointAdaptor
{
73 static void add(CodeBlock
*, JSArrayBufferView
*, Watchpoint
*);
74 static bool hasBeenInvalidated(JSArrayBufferView
* view
)
76 bool result
= !view
->length();
82 template<typename WatchpointSetType
, typename Adaptor
= GenericSetAdaptor
<WatchpointSetType
>>
83 class GenericDesiredWatchpoints
{
85 typedef HashMap
<WatchpointSetType
*, bool> StateMap
;
88 GenericDesiredWatchpoints()
89 : m_reallyAdded(false)
93 void addLazily(WatchpointSetType
* set
)
98 void addLazily(CodeOrigin codeOrigin
, ExitKind exitKind
, WatchpointSetType
* set
)
100 m_profiledWatchpoints
.append(
101 WatchpointForGenericWatchpointSet
<WatchpointSetType
>(codeOrigin
, exitKind
, set
));
104 void reallyAdd(CodeBlock
* codeBlock
, CommonData
& common
)
106 RELEASE_ASSERT(!m_reallyAdded
);
108 typename HashSet
<WatchpointSetType
*>::iterator iter
= m_sets
.begin();
109 typename HashSet
<WatchpointSetType
*>::iterator end
= m_sets
.end();
110 for (; iter
!= end
; ++iter
) {
111 common
.watchpoints
.append(CodeBlockJettisoningWatchpoint(codeBlock
));
112 Adaptor::add(codeBlock
, *iter
, &common
.watchpoints
.last());
115 for (unsigned i
= m_profiledWatchpoints
.size(); i
--;) {
116 WatchpointForGenericWatchpointSet
<WatchpointSetType
> watchpoint
=
117 m_profiledWatchpoints
[i
];
118 common
.profiledWatchpoints
.append(
119 ProfiledCodeBlockJettisoningWatchpoint(watchpoint
.m_codeOrigin
, watchpoint
.m_exitKind
, codeBlock
));
120 Adaptor::add(codeBlock
, watchpoint
.m_set
, &common
.profiledWatchpoints
.last());
123 m_reallyAdded
= true;
126 bool areStillValid() const
128 typename HashSet
<WatchpointSetType
*>::iterator iter
= m_sets
.begin();
129 typename HashSet
<WatchpointSetType
*>::iterator end
= m_sets
.end();
130 for (; iter
!= end
; ++iter
) {
131 if (Adaptor::hasBeenInvalidated(*iter
))
135 for (unsigned i
= m_profiledWatchpoints
.size(); i
--;) {
136 if (Adaptor::hasBeenInvalidated(m_profiledWatchpoints
[i
].m_set
))
144 bool isStillValid(WatchpointSetType
* set
)
146 return !Adaptor::hasBeenInvalidated(set
);
149 bool shouldAssumeMixedState(WatchpointSetType
*)
154 bool isStillValid(WatchpointSetType
* set
)
156 bool result
= !Adaptor::hasBeenInvalidated(set
);
157 m_firstKnownState
.add(set
, result
);
161 bool shouldAssumeMixedState(WatchpointSetType
* set
)
163 typename
StateMap::iterator iter
= m_firstKnownState
.find(set
);
164 if (iter
== m_firstKnownState
.end())
167 return iter
->value
!= !Adaptor::hasBeenInvalidated(set
);
171 bool isValidOrMixed(WatchpointSetType
* set
)
173 return isStillValid(set
) || shouldAssumeMixedState(set
);
177 Vector
<WatchpointForGenericWatchpointSet
<WatchpointSetType
>> m_profiledWatchpoints
;
178 HashSet
<WatchpointSetType
*> m_sets
;
180 StateMap m_firstKnownState
;
185 class DesiredWatchpoints
{
187 DesiredWatchpoints();
188 ~DesiredWatchpoints();
190 void addLazily(WatchpointSet
*);
191 void addLazily(InlineWatchpointSet
&);
192 void addLazily(JSArrayBufferView
*);
193 void addLazily(CodeOrigin
, ExitKind
, WatchpointSet
*);
194 void addLazily(CodeOrigin
, ExitKind
, InlineWatchpointSet
&);
196 void reallyAdd(CodeBlock
*, CommonData
&);
198 bool areStillValid() const;
200 bool isStillValid(WatchpointSet
* set
)
202 return m_sets
.isStillValid(set
);
204 bool isStillValid(InlineWatchpointSet
& set
)
206 return m_inlineSets
.isStillValid(&set
);
208 bool isStillValid(JSArrayBufferView
* view
)
210 return m_bufferViews
.isStillValid(view
);
212 bool shouldAssumeMixedState(WatchpointSet
* set
)
214 return m_sets
.shouldAssumeMixedState(set
);
216 bool shouldAssumeMixedState(InlineWatchpointSet
& set
)
218 return m_inlineSets
.shouldAssumeMixedState(&set
);
220 bool shouldAssumeMixedState(JSArrayBufferView
* view
)
222 return m_bufferViews
.shouldAssumeMixedState(view
);
224 bool isValidOrMixed(WatchpointSet
* set
)
226 return m_sets
.isValidOrMixed(set
);
228 bool isValidOrMixed(InlineWatchpointSet
& set
)
230 return m_inlineSets
.isValidOrMixed(&set
);
232 bool isValidOrMixed(JSArrayBufferView
* view
)
234 return m_bufferViews
.isValidOrMixed(view
);
238 GenericDesiredWatchpoints
<WatchpointSet
> m_sets
;
239 GenericDesiredWatchpoints
<InlineWatchpointSet
> m_inlineSets
;
240 GenericDesiredWatchpoints
<JSArrayBufferView
, ArrayBufferViewWatchpointAdaptor
> m_bufferViews
;
243 } } // namespace JSC::DFG
245 #endif // ENABLE(DFG_JIT)
247 #endif // DFGDesiredWatchpoints_h