52b3ed03b863901416511f0d34e3d2599ee03a11
[WebKit-https.git] / Source / JavaScriptCore / bytecode / StructureStubInfo.h
1 /*
2  * Copyright (C) 2008, 2012, 2013, 2014 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 "Opcode.h"
34 #include "PolymorphicAccessStructureList.h"
35 #include "RegisterSet.h"
36 #include "SpillRegistersMode.h"
37 #include "Structure.h"
38 #include "StructureStubClearingWatchpoint.h"
39 #include <wtf/OwnPtr.h>
40
41 namespace JSC {
42
43 #if ENABLE(JIT)
44
45 class PolymorphicPutByIdList;
46
47 enum AccessType {
48     access_get_by_id_self,
49     access_get_by_id_chain,
50     access_get_by_id_self_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_chain:
64     case access_get_by_id_self_list:
65         return true;
66     default:
67         return false;
68     }
69 }
70     
71 inline bool isPutByIdAccess(AccessType accessType)
72 {
73     switch (accessType) {
74     case access_put_by_id_transition_normal:
75     case access_put_by_id_transition_direct:
76     case access_put_by_id_replace:
77     case access_put_by_id_list:
78         return true;
79     default:
80         return false;
81     }
82 }
83
84 inline bool isInAccess(AccessType accessType)
85 {
86     switch (accessType) {
87     case access_in_list:
88         return true;
89     default:
90         return false;
91     }
92 }
93
94 struct StructureStubInfo {
95     StructureStubInfo()
96         : accessType(access_unset)
97         , seen(false)
98         , resetByGC(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 initGetByIdChain(VM& vm, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain, unsigned count, bool isDirect)
110     {
111         accessType = access_get_by_id_chain;
112
113         u.getByIdChain.baseObjectStructure.set(vm, owner, baseObjectStructure);
114         u.getByIdChain.chain.set(vm, owner, chain);
115         u.getByIdChain.count = count;
116         u.getByIdChain.isDirect = isDirect;
117     }
118
119     void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize, bool didSelfPatching = false)
120     {
121         accessType = access_get_by_id_self_list;
122
123         u.getByIdSelfList.structureList = structureList;
124         u.getByIdSelfList.listSize = listSize;
125         u.getByIdSelfList.didSelfPatching = didSelfPatching;
126     }
127
128     // PutById*
129
130     void initPutByIdTransition(VM& vm, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain, bool isDirect)
131     {
132         if (isDirect)
133             accessType = access_put_by_id_transition_direct;
134         else
135             accessType = access_put_by_id_transition_normal;
136
137         u.putByIdTransition.previousStructure.set(vm, owner, previousStructure);
138         u.putByIdTransition.structure.set(vm, owner, structure);
139         u.putByIdTransition.chain.set(vm, owner, chain);
140     }
141
142     void initPutByIdReplace(VM& vm, JSCell* owner, Structure* baseObjectStructure)
143     {
144         accessType = access_put_by_id_replace;
145     
146         u.putByIdReplace.baseObjectStructure.set(vm, owner, baseObjectStructure);
147     }
148         
149     void initPutByIdList(PolymorphicPutByIdList* list)
150     {
151         accessType = access_put_by_id_list;
152         u.putByIdList.list = list;
153     }
154     
155     void initInList(PolymorphicAccessStructureList* list, int listSize)
156     {
157         accessType = access_in_list;
158         u.inList.structureList = list;
159         u.inList.listSize = listSize;
160     }
161         
162     void reset()
163     {
164         deref();
165         accessType = access_unset;
166         stubRoutine.clear();
167         watchpoints.clear();
168     }
169
170     void deref();
171
172     bool visitWeakReferences();
173         
174     bool seenOnce()
175     {
176         return seen;
177     }
178
179     void setSeen()
180     {
181         seen = true;
182     }
183         
184     StructureStubClearingWatchpoint* addWatchpoint(CodeBlock* codeBlock)
185     {
186         return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint(
187             watchpoints, codeBlock, this);
188     }
189     
190     int8_t accessType;
191     bool seen : 1;
192     bool resetByGC : 1;
193
194     CodeOrigin codeOrigin;
195
196     struct {
197         SpillRegistersMode spillMode : 8;
198         int8_t baseGPR;
199 #if USE(JSVALUE32_64)
200         int8_t valueTagGPR;
201 #endif
202         int8_t valueGPR;
203         RegisterSet usedRegisters;
204         int32_t deltaCallToDone;
205         int32_t deltaCallToStorageLoad;
206         int32_t deltaCallToJump;
207         int32_t deltaCallToSlowCase;
208         int32_t deltaCheckImmToCall;
209 #if USE(JSVALUE64)
210         int32_t deltaCallToLoadOrStore;
211 #else
212         int32_t deltaCallToTagLoadOrStore;
213         int32_t deltaCallToPayloadLoadOrStore;
214 #endif
215     } patch;
216
217     union {
218         struct {
219             // It would be unwise to put anything here, as it will surely be overwritten.
220         } unset;
221         struct {
222             WriteBarrierBase<Structure> baseObjectStructure;
223         } getByIdSelf;
224         struct {
225             WriteBarrierBase<Structure> baseObjectStructure;
226             WriteBarrierBase<Structure> prototypeStructure;
227             bool isDirect;
228         } getByIdProto;
229         struct {
230             WriteBarrierBase<Structure> baseObjectStructure;
231             WriteBarrierBase<StructureChain> chain;
232             unsigned count : 31;
233             bool isDirect : 1;
234         } getByIdChain;
235         struct {
236             PolymorphicAccessStructureList* structureList;
237             int listSize : 31;
238             bool didSelfPatching : 1;
239         } getByIdSelfList;
240         struct {
241             PolymorphicAccessStructureList* structureList;
242             int listSize;
243         } getByIdProtoList;
244         struct {
245             WriteBarrierBase<Structure> previousStructure;
246             WriteBarrierBase<Structure> structure;
247             WriteBarrierBase<StructureChain> chain;
248         } putByIdTransition;
249         struct {
250             WriteBarrierBase<Structure> baseObjectStructure;
251         } putByIdReplace;
252         struct {
253             PolymorphicPutByIdList* list;
254         } putByIdList;
255         struct {
256             PolymorphicAccessStructureList* structureList;
257             int listSize;
258         } inList;
259     } u;
260
261     RefPtr<JITStubRoutine> stubRoutine;
262     CodeLocationCall callReturnLocation;
263     RefPtr<WatchpointsOnStructureStubInfo> watchpoints;
264 };
265
266 inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo)
267 {
268     return structureStubInfo.codeOrigin;
269 }
270
271 typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
272
273 #else
274
275 typedef HashMap<int, void*> StubInfoMap;
276
277 #endif // ENABLE(JIT)
278
279 } // namespace JSC
280
281 #endif // StructureStubInfo_h