]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/PolymorphicPutByIdList.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecode / PolymorphicPutByIdList.h
1 /*
2 * Copyright (C) 2012, 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 PolymorphicPutByIdList_h
27 #define PolymorphicPutByIdList_h
28
29 #if ENABLE(JIT)
30
31 #include "CodeOrigin.h"
32 #include "MacroAssembler.h"
33 #include "Opcode.h"
34 #include "PutKind.h"
35 #include "PutPropertySlot.h"
36 #include "Structure.h"
37 #include <wtf/Vector.h>
38
39 namespace JSC {
40
41 class CodeBlock;
42 struct StructureStubInfo;
43
44 class PutByIdAccess {
45 public:
46 enum AccessType {
47 Invalid,
48 Transition,
49 Replace,
50 Setter,
51 CustomSetter
52 };
53
54 PutByIdAccess()
55 : m_type(Invalid)
56 , m_chainCount(UINT_MAX)
57 {
58 }
59
60 static PutByIdAccess transition(
61 VM& vm,
62 JSCell* owner,
63 Structure* oldStructure,
64 Structure* newStructure,
65 StructureChain* chain,
66 PassRefPtr<JITStubRoutine> stubRoutine)
67 {
68 PutByIdAccess result;
69 result.m_type = Transition;
70 result.m_oldStructure.set(vm, owner, oldStructure);
71 result.m_newStructure.set(vm, owner, newStructure);
72 result.m_chain.set(vm, owner, chain);
73 result.m_customSetter = 0;
74 result.m_stubRoutine = stubRoutine;
75 return result;
76 }
77
78 static PutByIdAccess replace(
79 VM& vm,
80 JSCell* owner,
81 Structure* structure,
82 PassRefPtr<JITStubRoutine> stubRoutine)
83 {
84 PutByIdAccess result;
85 result.m_type = Replace;
86 result.m_oldStructure.set(vm, owner, structure);
87 result.m_customSetter = 0;
88 result.m_stubRoutine = stubRoutine;
89 return result;
90 }
91
92
93 static PutByIdAccess setter(
94 VM& vm,
95 JSCell* owner,
96 AccessType accessType,
97 Structure* structure,
98 StructureChain* chain,
99 unsigned chainCount,
100 PutPropertySlot::PutValueFunc customSetter,
101 PassRefPtr<JITStubRoutine> stubRoutine)
102 {
103 RELEASE_ASSERT(accessType == Setter || accessType == CustomSetter);
104 PutByIdAccess result;
105 result.m_oldStructure.set(vm, owner, structure);
106 result.m_type = accessType;
107 if (chain) {
108 result.m_chain.set(vm, owner, chain);
109 result.m_chainCount = chainCount;
110 }
111 result.m_customSetter = customSetter;
112 result.m_stubRoutine = stubRoutine;
113 return result;
114 }
115
116 static PutByIdAccess fromStructureStubInfo(StructureStubInfo&);
117
118 bool isSet() const { return m_type != Invalid; }
119 bool operator!() const { return !isSet(); }
120
121 AccessType type() const { return m_type; }
122
123 bool isTransition() const { return m_type == Transition; }
124 bool isReplace() const { return m_type == Replace; }
125 bool isSetter() const { return m_type == Setter; }
126 bool isCustom() const { return m_type == CustomSetter; }
127
128 Structure* oldStructure() const
129 {
130 // Using this instead of isSet() to make this assertion robust against the possibility
131 // of additional access types being added.
132 ASSERT(isTransition() || isReplace() || isSetter() || isCustom());
133
134 return m_oldStructure.get();
135 }
136
137 Structure* structure() const
138 {
139 ASSERT(isReplace() || isSetter() || isCustom());
140 return m_oldStructure.get();
141 }
142
143 Structure* newStructure() const
144 {
145 ASSERT(isTransition());
146 return m_newStructure.get();
147 }
148
149 StructureChain* chain() const
150 {
151 ASSERT(isTransition() || isSetter() || isCustom());
152 return m_chain.get();
153 }
154
155 unsigned chainCount() const
156 {
157 ASSERT(isSetter() || isCustom());
158 return m_chainCount;
159 }
160
161 JITStubRoutine* stubRoutine() const
162 {
163 ASSERT(isTransition() || isReplace() || isSetter() || isCustom());
164 return m_stubRoutine.get();
165 }
166
167 PutPropertySlot::PutValueFunc customSetter() const
168 {
169 ASSERT(isCustom());
170 return m_customSetter;
171 }
172
173 bool visitWeak(RepatchBuffer&) const;
174
175 private:
176 friend class CodeBlock;
177
178 AccessType m_type;
179 WriteBarrier<Structure> m_oldStructure;
180 WriteBarrier<Structure> m_newStructure;
181 WriteBarrier<StructureChain> m_chain;
182 unsigned m_chainCount;
183 PutPropertySlot::PutValueFunc m_customSetter;
184 RefPtr<JITStubRoutine> m_stubRoutine;
185 };
186
187 class PolymorphicPutByIdList {
188 WTF_MAKE_FAST_ALLOCATED;
189 public:
190 // Either creates a new polymorphic put list, or returns the one that is already
191 // in place.
192 static PolymorphicPutByIdList* from(PutKind, StructureStubInfo&);
193
194 ~PolymorphicPutByIdList();
195
196 MacroAssemblerCodePtr currentSlowPathTarget() const
197 {
198 return m_list.last().stubRoutine()->code().code();
199 }
200
201 void addAccess(const PutByIdAccess&);
202
203 bool isEmpty() const { return m_list.isEmpty(); }
204 unsigned size() const { return m_list.size(); }
205 bool isFull() const;
206 bool isAlmostFull() const; // True if adding an element would make isFull() true.
207 const PutByIdAccess& at(unsigned i) const { return m_list[i]; }
208 const PutByIdAccess& operator[](unsigned i) const { return m_list[i]; }
209
210 PutKind kind() const { return m_kind; }
211
212 bool visitWeak(RepatchBuffer&) const;
213
214 private:
215 friend class CodeBlock;
216
217 // Initialize from a stub info; this will place one element in the list and it will
218 // be created by converting the stub info's put by id access information into our
219 // PutByIdAccess.
220 PolymorphicPutByIdList(PutKind, StructureStubInfo&);
221
222 Vector<PutByIdAccess, 2> m_list;
223 PutKind m_kind;
224 };
225
226 } // namespace JSC
227
228 #endif // ENABLE(JIT)
229
230 #endif // PolymorphicPutByIdList_h
231