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 | |
36 | namespace JSC { namespace DFG { |
37 | |
38 | void 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 | |
56 | void 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 | |
68 | void 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 | |
80 | void 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 | |
106 | DesiredWatchpoints::DesiredWatchpoints() { } |
107 | DesiredWatchpoints::~DesiredWatchpoints() { } |
108 | |
109 | void DesiredWatchpoints::addLazily(WatchpointSet* set) |
110 | { |
111 | m_sets.addLazily(set); |
112 | } |
113 | |
114 | void DesiredWatchpoints::addLazily(InlineWatchpointSet& set) |
115 | { |
116 | m_inlineSets.addLazily(&set); |
117 | } |
118 | |
119 | void DesiredWatchpoints::addLazily(SymbolTable* symbolTable) |
120 | { |
121 | m_symbolTables.addLazily(symbolTable); |
122 | } |
123 | |
124 | void DesiredWatchpoints::addLazily(FunctionExecutable* executable) |
125 | { |
126 | m_functionExecutables.addLazily(executable); |
127 | } |
128 | |
129 | void DesiredWatchpoints::addLazily(JSArrayBufferView* view) |
130 | { |
131 | m_bufferViews.addLazily(view); |
132 | } |
133 | |
134 | void DesiredWatchpoints::addLazily(const ObjectPropertyCondition& key) |
135 | { |
136 | m_adaptiveStructureSets.addLazily(key); |
137 | } |
138 | |
139 | bool DesiredWatchpoints::consider(Structure* structure) |
140 | { |
141 | if (!structure->dfgShouldWatch()) |
142 | return false; |
143 | addLazily(structure->transitionWatchpointSet()); |
144 | return true; |
145 | } |
146 | |
147 | void 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 | |
157 | bool 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 | |
167 | void 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 | |