1/*
2 * Copyright (C) 2013-2019 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 "DFGDesiredWatchpoints.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "ArrayBufferNeuteringWatchpointSet.h"
32#include "CodeBlock.h"
33#include "DFGGraph.h"
34#include "JSCInlines.h"
35
36namespace JSC { namespace DFG {
37
38void ArrayBufferViewWatchpointAdaptor::add(
39 CodeBlock* codeBlock, JSArrayBufferView* view, CommonData& common)
40{
41 VM& vm = codeBlock->vm();
42 CodeBlockJettisoningWatchpoint* watchpoint = nullptr;
43 {
44 ConcurrentJSLocker locker(codeBlock->m_lock);
45 watchpoint = common.watchpoints.add(codeBlock);
46 }
47 ArrayBufferNeuteringWatchpointSet* neuteringWatchpoint =
48 ArrayBufferNeuteringWatchpointSet::create(vm);
49 neuteringWatchpoint->set().add(WTFMove(watchpoint));
50 codeBlock->addConstant(ConcurrentJSLocker(codeBlock->m_lock), neuteringWatchpoint);
51 // FIXME: We don't need to set this watchpoint at all for shared buffers.
52 // https://bugs.webkit.org/show_bug.cgi?id=164108
53 vm.heap.addReference(neuteringWatchpoint, view->possiblySharedBuffer());
54}
55
56void SymbolTableAdaptor::add(
57 CodeBlock* codeBlock, SymbolTable* symbolTable, CommonData& common)
58{
59 codeBlock->addConstant(ConcurrentJSLocker(codeBlock->m_lock), symbolTable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
60 CodeBlockJettisoningWatchpoint* watchpoint = nullptr;
61 {
62 ConcurrentJSLocker locker(codeBlock->m_lock);
63 watchpoint = common.watchpoints.add(codeBlock);
64 }
65 symbolTable->singleton().add(WTFMove(watchpoint));
66}
67
68void FunctionExecutableAdaptor::add(
69 CodeBlock* codeBlock, FunctionExecutable* executable, CommonData& common)
70{
71 codeBlock->addConstant(ConcurrentJSLocker(codeBlock->m_lock), executable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too.
72 CodeBlockJettisoningWatchpoint* watchpoint = nullptr;
73 {
74 ConcurrentJSLocker locker(codeBlock->m_lock);
75 watchpoint = common.watchpoints.add(codeBlock);
76 }
77 executable->singleton().add(WTFMove(watchpoint));
78}
79
80void AdaptiveStructureWatchpointAdaptor::add(
81 CodeBlock* codeBlock, const ObjectPropertyCondition& key, CommonData& common)
82{
83 VM& vm = codeBlock->vm();
84 switch (key.kind()) {
85 case PropertyCondition::Equivalence: {
86 AdaptiveInferredPropertyValueWatchpoint* watchpoint = nullptr;
87 {
88 ConcurrentJSLocker locker(codeBlock->m_lock);
89 watchpoint = common.adaptiveInferredPropertyValueWatchpoints.add(key, codeBlock);
90 }
91 watchpoint->install(vm);
92 break;
93 }
94 default: {
95 AdaptiveStructureWatchpoint* watchpoint = nullptr;
96 {
97 ConcurrentJSLocker locker(codeBlock->m_lock);
98 watchpoint = common.adaptiveStructureWatchpoints.add(key, codeBlock);
99 }
100 watchpoint->install(vm);
101 break;
102 }
103 }
104}
105
106DesiredWatchpoints::DesiredWatchpoints() { }
107DesiredWatchpoints::~DesiredWatchpoints() { }
108
109void DesiredWatchpoints::addLazily(WatchpointSet* set)
110{
111 m_sets.addLazily(set);
112}
113
114void DesiredWatchpoints::addLazily(InlineWatchpointSet& set)
115{
116 m_inlineSets.addLazily(&set);
117}
118
119void DesiredWatchpoints::addLazily(SymbolTable* symbolTable)
120{
121 m_symbolTables.addLazily(symbolTable);
122}
123
124void DesiredWatchpoints::addLazily(FunctionExecutable* executable)
125{
126 m_functionExecutables.addLazily(executable);
127}
128
129void DesiredWatchpoints::addLazily(JSArrayBufferView* view)
130{
131 m_bufferViews.addLazily(view);
132}
133
134void DesiredWatchpoints::addLazily(const ObjectPropertyCondition& key)
135{
136 m_adaptiveStructureSets.addLazily(key);
137}
138
139bool DesiredWatchpoints::consider(Structure* structure)
140{
141 if (!structure->dfgShouldWatch())
142 return false;
143 addLazily(structure->transitionWatchpointSet());
144 return true;
145}
146
147void DesiredWatchpoints::reallyAdd(CodeBlock* codeBlock, CommonData& commonData)
148{
149 m_sets.reallyAdd(codeBlock, commonData);
150 m_inlineSets.reallyAdd(codeBlock, commonData);
151 m_symbolTables.reallyAdd(codeBlock, commonData);
152 m_functionExecutables.reallyAdd(codeBlock, commonData);
153 m_bufferViews.reallyAdd(codeBlock, commonData);
154 m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
155}
156
157bool DesiredWatchpoints::areStillValid() const
158{
159 return m_sets.areStillValid()
160 && m_inlineSets.areStillValid()
161 && m_symbolTables.areStillValid()
162 && m_functionExecutables.areStillValid()
163 && m_bufferViews.areStillValid()
164 && m_adaptiveStructureSets.areStillValid();
165}
166
167void DesiredWatchpoints::dumpInContext(PrintStream& out, DumpContext* context) const
168{
169 Prefix noPrefix(Prefix::NoHeader);
170 Prefix& prefix = context && context->graph ? context->graph->prefix() : noPrefix;
171 out.print(prefix, "Desired watchpoints:\n");
172 out.print(prefix, " Watchpoint sets: ", inContext(m_sets, context), "\n");
173 out.print(prefix, " Inline watchpoint sets: ", inContext(m_inlineSets, context), "\n");
174 out.print(prefix, " SymbolTables: ", inContext(m_symbolTables, context), "\n");
175 out.print(prefix, " FunctionExecutables: ", inContext(m_functionExecutables, context), "\n");
176 out.print(prefix, " Buffer views: ", inContext(m_bufferViews, context), "\n");
177 out.print(prefix, " Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n");
178}
179
180} } // namespace JSC::DFG
181
182#endif // ENABLE(DFG_JIT)
183
184