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