DFG should have adaptive structure watchpoints
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGStructureRegistrationPhase.cpp
1 /*
2  * Copyright (C) 2014, 2015 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 "DFGStructureRegistrationPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGBasicBlockInlines.h"
32 #include "DFGGraph.h"
33 #include "DFGPhase.h"
34 #include "JSCInlines.h"
35
36 namespace JSC { namespace DFG {
37
38 class StructureRegistrationPhase : public Phase {
39 public:
40     StructureRegistrationPhase(Graph& graph)
41         : Phase(graph, "structure registration")
42     {
43     }
44     
45     bool run()
46     {
47         // We need to set this before this phase finishes. This phase doesn't do anything
48         // conditioned on this field, except for assertIsRegistered() below. We intend for that
49         // method to behave as if the phase was already finished. So, we set this up here.
50         m_graph.m_structureRegistrationState = AllStructuresAreRegistered;
51         
52         // These are pretty dumb, but needed to placate subsequent assertions. We don't actually
53         // have to watch these because there is no way to transition away from it, but they are
54         // watchable and so we will assert if they aren't watched.
55         registerStructure(m_graph.m_vm.structureStructure.get());
56         registerStructure(m_graph.m_vm.stringStructure.get());
57         registerStructure(m_graph.m_vm.getterSetterStructure.get());
58         
59         for (FrozenValue* value : m_graph.m_frozenValues)
60             m_graph.assertIsRegistered(value->structure());
61         
62         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
63             BasicBlock* block = m_graph.block(blockIndex);
64             if (!block)
65                 continue;
66         
67             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
68                 Node* node = block->at(nodeIndex);
69             
70                 switch (node->op()) {
71                 case CheckStructure:
72                     registerStructures(node->structureSet());
73                     break;
74                 
75                 case NewObject:
76                 case ArrayifyToStructure:
77                 case NewStringObject:
78                     registerStructure(node->structure());
79                     break;
80                 
81                 case PutStructure:
82                 case AllocatePropertyStorage:
83                 case ReallocatePropertyStorage:
84                     registerStructure(node->transition()->previous);
85                     registerStructure(node->transition()->next);
86                     break;
87                     
88                 case MultiGetByOffset:
89                     for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases)
90                         registerStructures(getCase.set());
91                     break;
92                     
93                 case MultiPutByOffset:
94                     for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
95                         PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
96                         registerStructures(variant.oldStructure());
97                         if (variant.kind() == PutByIdVariant::Transition)
98                             registerStructure(variant.newStructure());
99                     }
100                     break;
101                     
102                 case NewArray:
103                 case NewArrayBuffer:
104                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
105                     break;
106                     
107                 case NewTypedArray:
108                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructure(node->typedArrayType()));
109                     break;
110                     
111                 case ToString:
112                 case CallStringConstructor:
113                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
114                     break;
115                     
116                 case CreateActivation:
117                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->activationStructure());
118                     break;
119                     
120                 case CreateDirectArguments:
121                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->directArgumentsStructure());
122                     break;
123                     
124                 case CreateScopedArguments:
125                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
126                     break;
127                     
128                 case NewRegexp:
129                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
130                     break;
131                     
132                 case NewFunction:
133                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->functionStructure());
134                     break;
135                     
136                 default:
137                     break;
138                 }
139             }
140         }
141         
142         return true;
143     }
144
145 private:
146     void registerStructures(const StructureSet& set)
147     {
148         for (unsigned i = set.size(); i--;)
149             registerStructure(set[i]);
150     }
151     
152     void registerStructure(Structure* structure)
153     {
154         if (structure)
155             m_graph.registerStructure(structure);
156     }
157 };
158
159 bool performStructureRegistration(Graph& graph)
160 {
161     SamplingRegion samplingRegion("DFG Structure Registration Phase");
162     return runPhase<StructureRegistrationPhase>(graph);
163 }
164
165 } } // namespace JSC::DFG
166
167 #endif // ENABLE(DFG_JIT)
168