DFG should have adaptive structure watchpoints
[WebKit-https.git] / Source / JavaScriptCore / bytecode / StructureStubInfo.h
1 /*
2  * Copyright (C) 2008, 2012-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 #ifndef StructureStubInfo_h
27 #define StructureStubInfo_h
28
29 #include "CodeOrigin.h"
30 #include "Instruction.h"
31 #include "JITStubRoutine.h"
32 #include "MacroAssembler.h"
33 #include "ObjectPropertyConditionSet.h"
34 #include "Opcode.h"
35 #include "PolymorphicAccessStructureList.h"
36 #include "RegisterSet.h"
37 #include "SpillRegistersMode.h"
38 #include "Structure.h"
39 #include "StructureStubClearingWatchpoint.h"
40
41 namespace JSC {
42
43 #if ENABLE(JIT)
44
45 class PolymorphicGetByIdList;
46 class PolymorphicPutByIdList;
47
48 enum AccessType {
49     access_get_by_id_self,
50     access_get_by_id_list,
51     access_put_by_id_transition_normal,
52     access_put_by_id_transition_direct,
53     access_put_by_id_replace,
54     access_put_by_id_list,
55     access_unset,
56     access_in_list
57 };
58
59 inline bool isGetByIdAccess(AccessType accessType)
60 {
61     switch (accessType) {
62     case access_get_by_id_self:
63     case access_get_by_id_list:
64         return true;
65     default:
66         return false;
67     }
68 }
69     
70 inline bool isPutByIdAccess(AccessType accessType)
71 {
72     switch (accessType) {
73     case access_put_by_id_transition_normal:
74     case access_put_by_id_transition_direct:
75     case access_put_by_id_replace:
76     case access_put_by_id_list:
77         return true;
78     default:
79         return false;
80     }
81 }
82
83 inline bool isInAccess(AccessType accessType)
84 {
85     switch (accessType) {
86     case access_in_list:
87         return true;
88     default:
89         return false;
90     }
91 }
92
93 struct StructureStubInfo {
94     StructureStubInfo()
95         : accessType(access_unset)
96         , seen(false)
97         , resetByGC(false)
98         , tookSlowPath(false)
99     {
100     }
101
102     void initGetByIdSelf(VM& vm, JSCell* owner, Structure* baseObjectStructure)
103     {
104         accessType = access_get_by_id_self;
105
106         u.getByIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure);
107     }
108
109     void initGetByIdList(PolymorphicGetByIdList* list)
110     {
111         accessType = access_get_by_id_list;
112         u.getByIdList.list = list;
113     }
114
115     // PutById*
116
117     void initPutByIdTransition(VM& vm, JSCell* owner, Structure* previousStructure, Structure* structure, ObjectPropertyConditionSet conditionSet, bool isDirect)
118     {
119         if (isDirect)
120             accessType = access_put_by_id_transition_direct;
121         else
122             accessType = access_put_by_id_transition_normal;
123
124         u.putByIdTransition.previousStructure.set(vm, owner, previousStructure);
125         u.putByIdTransition.structure.set(vm, owner, structure);
126         u.putByIdTransition.rawConditionSet = conditionSet.releaseRawPointer();
127     }
128
129     void initPutByIdReplace(VM& vm, JSCell* owner, Structure* baseObjectStructure)
130     {
131         accessType = access_put_by_id_replace;
132     
133         u.putByIdReplace.baseObjectStructure.set(vm, owner, baseObjectStructure);
134     }
135         
136     void initPutByIdList(PolymorphicPutByIdList* list)
137     {
138         accessType = access_put_by_id_list;
139         u.putByIdList.list = list;
140     }
141     
142     void initInList(PolymorphicAccessStructureList* list, int listSize)
143     {
144         accessType = access_in_list;
145         u.inList.structureList = list;
146         u.inList.listSize = listSize;
147     }
148         
149     void reset()
150     {
151         deref();
152         accessType = access_unset;
153         stubRoutine = nullptr;
154         watchpoints = nullptr;
155     }
156
157     void deref();
158
159     // Check if the stub has weak references that are dead. If there are dead ones that imply
160     // that the stub should be entirely reset, this should return false. If there are dead ones
161     // that can be handled internally by the stub and don't require a full reset, then this
162     // should reset them and return true. If there are no dead weak references, return true.
163     // If this method returns true it means that it has left the stub in a state where all
164     // outgoing GC pointers are known to point to currently marked objects; this method is
165     // allowed to accomplish this by either clearing those pointers somehow or by proving that
166     // they have already been marked. It is not allowed to mark new objects.
167     bool visitWeakReferences(RepatchBuffer&);
168         
169     bool seenOnce()
170     {
171         return seen;
172     }
173
174     void setSeen()
175     {
176         seen = true;
177     }
178         
179     StructureStubClearingWatchpoint* addWatchpoint(
180         CodeBlock* codeBlock, const ObjectPropertyCondition& condition = ObjectPropertyCondition())
181     {
182         return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint(
183             watchpoints, codeBlock, this, condition);
184     }
185     
186     int8_t accessType;
187     bool seen : 1;
188     bool resetByGC : 1;
189     bool tookSlowPath : 1;
190
191     CodeOrigin codeOrigin;
192
193     struct {
194         unsigned spillMode : 8;
195         int8_t baseGPR;
196 #if USE(JSVALUE32_64)
197         int8_t valueTagGPR;
198 #endif
199         int8_t valueGPR;
200         RegisterSet usedRegisters;
201         int32_t deltaCallToDone;
202         int32_t deltaCallToStorageLoad;
203         int32_t deltaCallToJump;
204         int32_t deltaCallToSlowCase;
205         int32_t deltaCheckImmToCall;
206 #if USE(JSVALUE64)
207         int32_t deltaCallToLoadOrStore;
208 #else
209         int32_t deltaCallToTagLoadOrStore;
210         int32_t deltaCallToPayloadLoadOrStore;
211 #endif
212     } patch;
213
214     union {
215         struct {
216             // It would be unwise to put anything here, as it will surely be overwritten.
217         } unset;
218         struct {
219             WriteBarrierBase<Structure> baseObjectStructure;
220         } getByIdSelf;
221         struct {
222             PolymorphicGetByIdList* list;
223         } getByIdList;
224         struct {
225             WriteBarrierBase<Structure> previousStructure;
226             WriteBarrierBase<Structure> structure;
227             void* rawConditionSet;
228         } putByIdTransition;
229         struct {
230             WriteBarrierBase<Structure> baseObjectStructure;
231         } putByIdReplace;
232         struct {
233             PolymorphicPutByIdList* list;
234         } putByIdList;
235         struct {
236             PolymorphicAccessStructureList* structureList;
237             int listSize;
238         } inList;
239     } u;
240
241     RefPtr<JITStubRoutine> stubRoutine;
242     CodeLocationCall callReturnLocation;
243     RefPtr<WatchpointsOnStructureStubInfo> watchpoints;
244 };
245
246 inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo)
247 {
248     return structureStubInfo.codeOrigin;
249 }
250
251 typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
252
253 #else
254
255 typedef HashMap<int, void*> StubInfoMap;
256
257 #endif // ENABLE(JIT)
258
259 } // namespace JSC
260
261 #endif // StructureStubInfo_h