My favorites | Sign in
v8
Project Home Downloads Wiki Issues Source Code Search
Checkout   Browse   Changes  
Changes to /trunk/src/ic.h
r11798 vs. r12643 Compare: vs.  Format:
Revision r12643
Go to: 
Project members, sign in to write a code review
/trunk/src/ic.h   r11798 /trunk/src/ic.h   r12643
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifndef V8_IC_H_ 28 #ifndef V8_IC_H_
29 #define V8_IC_H_ 29 #define V8_IC_H_
30 30
31 #include "macro-assembler.h" 31 #include "macro-assembler.h"
32 #include "type-info.h" 32 #include "type-info.h"
33 33
34 namespace v8 { 34 namespace v8 {
35 namespace internal { 35 namespace internal {
36 36
37 37
38 // IC_UTIL_LIST defines all utility functions called from generated 38 // IC_UTIL_LIST defines all utility functions called from generated
39 // inline caching code. The argument for the macro, ICU, is the function name. 39 // inline caching code. The argument for the macro, ICU, is the function name.
40 #define IC_UTIL_LIST(ICU) \ 40 #define IC_UTIL_LIST(ICU) \
41 ICU(LoadIC_Miss) \ 41 ICU(LoadIC_Miss) \
42 ICU(KeyedLoadIC_Miss) \ 42 ICU(KeyedLoadIC_Miss) \
43 ICU(KeyedLoadIC_MissForceGeneric) \ 43 ICU(KeyedLoadIC_MissForceGeneric) \
44 ICU(CallIC_Miss) \ 44 ICU(CallIC_Miss) \
45 ICU(KeyedCallIC_Miss) \ 45 ICU(KeyedCallIC_Miss) \
46 ICU(StoreIC_Miss) \ 46 ICU(StoreIC_Miss) \
47 ICU(StoreIC_ArrayLength) \ 47 ICU(StoreIC_ArrayLength) \
48 ICU(SharedStoreIC_ExtendStorage) \ 48 ICU(SharedStoreIC_ExtendStorage) \
49 ICU(KeyedStoreIC_Miss) \ 49 ICU(KeyedStoreIC_Miss) \
50 ICU(KeyedStoreIC_MissForceGeneric) \ 50 ICU(KeyedStoreIC_MissForceGeneric) \
51 ICU(KeyedStoreIC_Slow) \ 51 ICU(KeyedStoreIC_Slow) \
52 /* Utilities for IC stubs. */ \ 52 /* Utilities for IC stubs. */ \
53 ICU(LoadCallbackProperty) \ 53 ICU(LoadCallbackProperty) \
54 ICU(StoreCallbackProperty) \ 54 ICU(StoreCallbackProperty) \
55 ICU(LoadPropertyWithInterceptorOnly) \ 55 ICU(LoadPropertyWithInterceptorOnly) \
56 ICU(LoadPropertyWithInterceptorForLoad) \ 56 ICU(LoadPropertyWithInterceptorForLoad) \
57 ICU(LoadPropertyWithInterceptorForCall) \ 57 ICU(LoadPropertyWithInterceptorForCall) \
58 ICU(KeyedLoadPropertyWithInterceptor) \ 58 ICU(KeyedLoadPropertyWithInterceptor) \
59 ICU(StoreInterceptorProperty) \ 59 ICU(StoreInterceptorProperty) \
60 ICU(UnaryOp_Patch) \ 60 ICU(UnaryOp_Patch) \
61 ICU(BinaryOp_Patch) \ 61 ICU(BinaryOp_Patch) \
62 ICU(CompareIC_Miss) \ 62 ICU(CompareIC_Miss) \
63 ICU(ToBoolean_Patch) 63 ICU(ToBoolean_Patch)
64 // 64 //
65 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC, 65 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
66 // and KeyedStoreIC. 66 // and KeyedStoreIC.
67 // 67 //
68 class IC { 68 class IC {
69 public: 69 public:
70 // The ids for utility called from the generated code. 70 // The ids for utility called from the generated code.
71 enum UtilityId { 71 enum UtilityId {
72 #define CONST_NAME(name) k##name, 72 #define CONST_NAME(name) k##name,
73 IC_UTIL_LIST(CONST_NAME) 73 IC_UTIL_LIST(CONST_NAME)
74 #undef CONST_NAME 74 #undef CONST_NAME
75 kUtilityCount 75 kUtilityCount
76 }; 76 };
77 77
78 // Looks up the address of the named utility. 78 // Looks up the address of the named utility.
79 static Address AddressFromUtilityId(UtilityId id); 79 static Address AddressFromUtilityId(UtilityId id);
80 80
81 // Alias the inline cache state type to make the IC code more readable. 81 // Alias the inline cache state type to make the IC code more readable.
82 typedef InlineCacheState State; 82 typedef InlineCacheState State;
83 83
84 // The IC code is either invoked with no extra frames on the stack 84 // The IC code is either invoked with no extra frames on the stack
85 // or with a single extra frame for supporting calls. 85 // or with a single extra frame for supporting calls.
86 enum FrameDepth { 86 enum FrameDepth {
87 NO_EXTRA_FRAME = 0, 87 NO_EXTRA_FRAME = 0,
88 EXTRA_CALL_FRAME = 1 88 EXTRA_CALL_FRAME = 1
89 }; 89 };
90 90
91 // Construct the IC structure with the given number of extra 91 // Construct the IC structure with the given number of extra
92 // JavaScript frames on the stack. 92 // JavaScript frames on the stack.
93 IC(FrameDepth depth, Isolate* isolate); 93 IC(FrameDepth depth, Isolate* isolate);
94 virtual ~IC() {} 94 virtual ~IC() {}
95 95
96 // Get the call-site target; used for determining the state. 96 // Get the call-site target; used for determining the state.
97 Code* target() const { return GetTargetAtAddress(address()); } 97 Code* target() const { return GetTargetAtAddress(address()); }
98 inline Address address() const; 98 inline Address address() const;
99 99
100 virtual bool IsGeneric() const { return false; } 100 virtual bool IsGeneric() const { return false; }
101 101
102 // Compute the current IC state based on the target stub, receiver and name. 102 // Compute the current IC state based on the target stub, receiver and name.
103 static State StateFrom(Code* target, Object* receiver, Object* name); 103 static State StateFrom(Code* target, Object* receiver, Object* name);
104 104
105 // Clear the inline cache to initial state. 105 // Clear the inline cache to initial state.
106 static void Clear(Address address); 106 static void Clear(Address address);
107 107
108 // Computes the reloc info for this IC. This is a fairly expensive 108 // Computes the reloc info for this IC. This is a fairly expensive
109 // operation as it has to search through the heap to find the code 109 // operation as it has to search through the heap to find the code
110 // object that contains this IC site. 110 // object that contains this IC site.
111 RelocInfo::Mode ComputeMode(); 111 RelocInfo::Mode ComputeMode();
112 112
113 // Returns if this IC is for contextual (no explicit receiver) 113 // Returns if this IC is for contextual (no explicit receiver)
114 // access to properties. 114 // access to properties.
115 bool IsContextual(Handle<Object> receiver) { 115 bool IsContextual(Handle<Object> receiver) {
116 if (receiver->IsGlobalObject()) { 116 if (receiver->IsGlobalObject()) {
117 return SlowIsContextual(); 117 return SlowIsContextual();
118 } else { 118 } else {
119 ASSERT(!SlowIsContextual()); 119 ASSERT(!SlowIsContextual());
120 return false; 120 return false;
121 } 121 }
122 } 122 }
123 123
124 bool SlowIsContextual() { 124 bool SlowIsContextual() {
125 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT; 125 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
126 } 126 }
127 127
128 // Determines which map must be used for keeping the code stub. 128 // Determines which map must be used for keeping the code stub.
129 // These methods should not be called with undefined or null. 129 // These methods should not be called with undefined or null.
130 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object, 130 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
131 JSObject* holder); 131 JSObject* holder);
132 static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object, 132 static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
133 JSObject* holder); 133 JSObject* holder);
134 static inline JSObject* GetCodeCacheHolder(Object* object, 134 static inline JSObject* GetCodeCacheHolder(Object* object,
135 InlineCacheHolderFlag holder); 135 InlineCacheHolderFlag holder);
136 136
137 protected: 137 protected:
138 Address fp() const { return fp_; } 138 Address fp() const { return fp_; }
139 Address pc() const { return *pc_address_; } 139 Address pc() const { return *pc_address_; }
140 Isolate* isolate() const { return isolate_; } 140 Isolate* isolate() const { return isolate_; }
141 141
142 #ifdef ENABLE_DEBUGGER_SUPPORT 142 #ifdef ENABLE_DEBUGGER_SUPPORT
143 // Computes the address in the original code when the code running is 143 // Computes the address in the original code when the code running is
144 // containing break points (calls to DebugBreakXXX builtins). 144 // containing break points (calls to DebugBreakXXX builtins).
145 Address OriginalCodeAddress() const; 145 Address OriginalCodeAddress() const;
146 #endif 146 #endif
147 147
148 // Set the call-site target. 148 // Set the call-site target.
149 void set_target(Code* code) { SetTargetAtAddress(address(), code); } 149 void set_target(Code* code) { SetTargetAtAddress(address(), code); }
150 150
151 #ifdef DEBUG 151 #ifdef DEBUG
152 char TransitionMarkFromState(IC::State state); 152 char TransitionMarkFromState(IC::State state);
153 153
154 void TraceIC(const char* type, 154 void TraceIC(const char* type,
155 Handle<Object> name, 155 Handle<Object> name,
156 State old_state, 156 State old_state,
157 Code* new_target); 157 Code* new_target);
158 #endif 158 #endif
159 159
160 Failure* TypeError(const char* type, 160 Failure* TypeError(const char* type,
161 Handle<Object> object, 161 Handle<Object> object,
162 Handle<Object> key); 162 Handle<Object> key);
163 Failure* ReferenceError(const char* type, Handle<String> name); 163 Failure* ReferenceError(const char* type, Handle<String> name);
164 164
165 // Access the target code for the given IC address. 165 // Access the target code for the given IC address.
166 static inline Code* GetTargetAtAddress(Address address); 166 static inline Code* GetTargetAtAddress(Address address);
167 static inline void SetTargetAtAddress(Address address, Code* target); 167 static inline void SetTargetAtAddress(Address address, Code* target);
168 static void PostPatching(Address address, Code* target, Code* old_target); 168 static void PostPatching(Address address, Code* target, Code* old_target);
169 169
170 private: 170 private:
171 // Frame pointer for the frame that uses (calls) the IC. 171 // Frame pointer for the frame that uses (calls) the IC.
172 Address fp_; 172 Address fp_;
173 173
174 // All access to the program counter of an IC structure is indirect 174 // All access to the program counter of an IC structure is indirect
175 // to make the code GC safe. This feature is crucial since 175 // to make the code GC safe. This feature is crucial since
176 // GetProperty and SetProperty are called and they in turn might 176 // GetProperty and SetProperty are called and they in turn might
177 // invoke the garbage collector. 177 // invoke the garbage collector.
178 Address* pc_address_; 178 Address* pc_address_;
179 179
180 Isolate* isolate_; 180 Isolate* isolate_;
181 181
182 DISALLOW_IMPLICIT_CONSTRUCTORS(IC); 182 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
183 }; 183 };
184 184
185 185
186 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you 186 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
187 // cannot make forward declarations to an enum. 187 // cannot make forward declarations to an enum.
188 class IC_Utility { 188 class IC_Utility {
189 public: 189 public:
190 explicit IC_Utility(IC::UtilityId id) 190 explicit IC_Utility(IC::UtilityId id)
191 : address_(IC::AddressFromUtilityId(id)), id_(id) {} 191 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
192 192
193 Address address() const { return address_; } 193 Address address() const { return address_; }
194 194
195 IC::UtilityId id() const { return id_; } 195 IC::UtilityId id() const { return id_; }
196 private: 196 private:
197 Address address_; 197 Address address_;
198 IC::UtilityId id_; 198 IC::UtilityId id_;
199 }; 199 };
200 200
201 201
202 class CallICBase: public IC { 202 class CallICBase: public IC {
203 public: 203 public:
204 class Contextual: public BitField<bool, 0, 1> {}; 204 class Contextual: public BitField<bool, 0, 1> {};
205 class StringStubState: public BitField<StringStubFeedback, 1, 1> {}; 205 class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
206 206
207 // Returns a JSFunction or a Failure. 207 // Returns a JSFunction or a Failure.
208 MUST_USE_RESULT MaybeObject* LoadFunction(State state, 208 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
209 Code::ExtraICState extra_ic_state, 209 Code::ExtraICState extra_ic_state,
210 Handle<Object> object, 210 Handle<Object> object,
211 Handle<String> name); 211 Handle<String> name);
212 212
213 protected: 213 protected:
214 CallICBase(Code::Kind kind, Isolate* isolate) 214 CallICBase(Code::Kind kind, Isolate* isolate)
215 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {} 215 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
216 216
217 bool TryUpdateExtraICState(LookupResult* lookup, 217 bool TryUpdateExtraICState(LookupResult* lookup,
218 Handle<Object> object, 218 Handle<Object> object,
219 Code::ExtraICState* extra_ic_state); 219 Code::ExtraICState* extra_ic_state);
220 220
221 // Compute a monomorphic stub if possible, otherwise return a null handle. 221 // Compute a monomorphic stub if possible, otherwise return a null handle.
222 Handle<Code> ComputeMonomorphicStub(LookupResult* lookup, 222 Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
223 State state, 223 State state,
224 Code::ExtraICState extra_state, 224 Code::ExtraICState extra_state,
225 Handle<Object> object, 225 Handle<Object> object,
226 Handle<String> name); 226 Handle<String> name);
227 227
228 // Update the inline cache and the global stub cache based on the lookup 228 // Update the inline cache and the global stub cache based on the lookup
229 // result. 229 // result.
230 void UpdateCaches(LookupResult* lookup, 230 void UpdateCaches(LookupResult* lookup,
231 State state, 231 State state,
232 Code::ExtraICState extra_ic_state, 232 Code::ExtraICState extra_ic_state,
233 Handle<Object> object, 233 Handle<Object> object,
234 Handle<String> name); 234 Handle<String> name);
235 235
236 // Returns a JSFunction if the object can be called as a function, and 236 // Returns a JSFunction if the object can be called as a function, and
237 // patches the stack to be ready for the call. Otherwise, it returns the 237 // patches the stack to be ready for the call. Otherwise, it returns the
238 // undefined value. 238 // undefined value.
239 Handle<Object> TryCallAsFunction(Handle<Object> object); 239 Handle<Object> TryCallAsFunction(Handle<Object> object);
240 240
241 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object); 241 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
242 242
243 static void Clear(Address address, Code* target); 243 static void Clear(Address address, Code* target);
244 244
245 // Platform-specific code generation functions used by both call and 245 // Platform-specific code generation functions used by both call and
246 // keyed call. 246 // keyed call.
247 static void GenerateMiss(MacroAssembler* masm, 247 static void GenerateMiss(MacroAssembler* masm,
248 int argc, 248 int argc,
249 IC::UtilityId id, 249 IC::UtilityId id,
250 Code::ExtraICState extra_state); 250 Code::ExtraICState extra_state);
251 251
252 static void GenerateNormal(MacroAssembler* masm, int argc); 252 static void GenerateNormal(MacroAssembler* masm, int argc);
253 253
254 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 254 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
255 int argc, 255 int argc,
256 Code::Kind kind, 256 Code::Kind kind,
257 Code::ExtraICState extra_state); 257 Code::ExtraICState extra_state);
258 258
259 Code::Kind kind_; 259 Code::Kind kind_;
260 260
261 friend class IC; 261 friend class IC;
262 }; 262 };
263 263
264 264
265 class CallIC: public CallICBase { 265 class CallIC: public CallICBase {
266 public: 266 public:
267 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) { 267 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
268 ASSERT(target()->is_call_stub()); 268 ASSERT(target()->is_call_stub());
269 } 269 }
270 270
271 // Code generator routines. 271 // Code generator routines.
272 static void GenerateInitialize(MacroAssembler* masm, 272 static void GenerateInitialize(MacroAssembler* masm,
273 int argc, 273 int argc,
274 Code::ExtraICState extra_state) { 274 Code::ExtraICState extra_state) {
275 GenerateMiss(masm, argc, extra_state); 275 GenerateMiss(masm, argc, extra_state);
276 } 276 }
277 277
278 static void GenerateMiss(MacroAssembler* masm, 278 static void GenerateMiss(MacroAssembler* masm,
279 int argc, 279 int argc,
280 Code::ExtraICState extra_state) { 280 Code::ExtraICState extra_state) {
281 CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state); 281 CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
282 } 282 }
283 283
284 static void GenerateMegamorphic(MacroAssembler* masm, 284 static void GenerateMegamorphic(MacroAssembler* masm,
285 int argc, 285 int argc,
286 Code::ExtraICState extra_ic_state); 286 Code::ExtraICState extra_ic_state);
287 287
288 static void GenerateNormal(MacroAssembler* masm, int argc) { 288 static void GenerateNormal(MacroAssembler* masm, int argc) {
289 CallICBase::GenerateNormal(masm, argc); 289 CallICBase::GenerateNormal(masm, argc);
290 GenerateMiss(masm, argc, Code::kNoExtraICState); 290 GenerateMiss(masm, argc, Code::kNoExtraICState);
291 } 291 }
292 }; 292 };
293 293
294 294
295 class KeyedCallIC: public CallICBase { 295 class KeyedCallIC: public CallICBase {
296 public: 296 public:
297 explicit KeyedCallIC(Isolate* isolate) 297 explicit KeyedCallIC(Isolate* isolate)
298 : CallICBase(Code::KEYED_CALL_IC, isolate) { 298 : CallICBase(Code::KEYED_CALL_IC, isolate) {
299 ASSERT(target()->is_keyed_call_stub()); 299 ASSERT(target()->is_keyed_call_stub());
300 } 300 }
301 301
302 MUST_USE_RESULT MaybeObject* LoadFunction(State state, 302 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
303 Handle<Object> object, 303 Handle<Object> object,
304 Handle<Object> key); 304 Handle<Object> key);
305 305
306 // Code generator routines. 306 // Code generator routines.
307 static void GenerateInitialize(MacroAssembler* masm, int argc) { 307 static void GenerateInitialize(MacroAssembler* masm, int argc) {
308 GenerateMiss(masm, argc); 308 GenerateMiss(masm, argc);
309 } 309 }
310 310
311 static void GenerateMiss(MacroAssembler* masm, int argc) { 311 static void GenerateMiss(MacroAssembler* masm, int argc) {
312 CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss, 312 CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
313 Code::kNoExtraICState); 313 Code::kNoExtraICState);
314 } 314 }
315 315
316 static void GenerateMegamorphic(MacroAssembler* masm, int argc); 316 static void GenerateMegamorphic(MacroAssembler* masm, int argc);
317 static void GenerateNormal(MacroAssembler* masm, int argc); 317 static void GenerateNormal(MacroAssembler* masm, int argc);
318 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc); 318 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
319 }; 319 };
320 320
321 321
322 class LoadIC: public IC { 322 class LoadIC: public IC {
323 public: 323 public:
324 explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { 324 explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
325 ASSERT(target()->is_load_stub()); 325 ASSERT(target()->is_load_stub());
326 } 326 }
327 327
328 MUST_USE_RESULT MaybeObject* Load(State state, 328 MUST_USE_RESULT MaybeObject* Load(State state,
329 Handle<Object> object, 329 Handle<Object> object,
330 Handle<String> name); 330 Handle<String> name);
331 331
332 // Code generator routines. 332 // Code generator routines.
333 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } 333 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
334 static void GeneratePreMonomorphic(MacroAssembler* masm) { 334 static void GeneratePreMonomorphic(MacroAssembler* masm) {
335 GenerateMiss(masm); 335 GenerateMiss(masm);
336 } 336 }
337 static void GenerateMiss(MacroAssembler* masm); 337 static void GenerateMiss(MacroAssembler* masm);
338 static void GenerateMegamorphic(MacroAssembler* masm); 338 static void GenerateMegamorphic(MacroAssembler* masm);
339 static void GenerateNormal(MacroAssembler* masm); 339 static void GenerateNormal(MacroAssembler* masm);
340 340
341 // Specialized code generator routines. 341 // Specialized code generator routines.
342 static void GenerateArrayLength(MacroAssembler* masm); 342 static void GenerateArrayLength(MacroAssembler* masm);
343 static void GenerateStringLength(MacroAssembler* masm, 343 static void GenerateStringLength(MacroAssembler* masm,
344 bool support_wrappers); 344 bool support_wrappers);
345 static void GenerateFunctionPrototype(MacroAssembler* masm); 345 static void GenerateFunctionPrototype(MacroAssembler* masm);
346 346
347 private: 347 private:
348 // Update the inline cache and the global stub cache based on the 348 // Update the inline cache and the global stub cache based on the
349 // lookup result. 349 // lookup result.
350 void UpdateCaches(LookupResult* lookup, 350 void UpdateCaches(LookupResult* lookup,
351 State state, 351 State state,
352 Handle<Object> object, 352 Handle<Object> object,
353 Handle<String> name); 353 Handle<String> name);
354 354
355 // Stub accessors. 355 // Stub accessors.
356 Handle<Code> megamorphic_stub() { 356 Handle<Code> megamorphic_stub() {
357 return isolate()->builtins()->LoadIC_Megamorphic(); 357 return isolate()->builtins()->LoadIC_Megamorphic();
358 } 358 }
359 static Code* initialize_stub() { 359 static Code* initialize_stub() {
360 return Isolate::Current()->builtins()->builtin( 360 return Isolate::Current()->builtins()->builtin(
361 Builtins::kLoadIC_Initialize); 361 Builtins::kLoadIC_Initialize);
362 } 362 }
363 Handle<Code> pre_monomorphic_stub() { 363 Handle<Code> pre_monomorphic_stub() {
364 return isolate()->builtins()->LoadIC_PreMonomorphic(); 364 return isolate()->builtins()->LoadIC_PreMonomorphic();
365 } 365 }
366 366
367 static void Clear(Address address, Code* target); 367 static void Clear(Address address, Code* target);
368 368
369 friend class IC; 369 friend class IC;
370 }; 370 };
371 371
372 372
373 class KeyedIC: public IC { 373 class KeyedIC: public IC {
374 public: 374 public:
375 enum StubKind { 375 enum StubKind {
376 LOAD, 376 LOAD,
377 STORE_NO_TRANSITION, 377 STORE_NO_TRANSITION,
378 STORE_TRANSITION_SMI_TO_OBJECT, 378 STORE_TRANSITION_SMI_TO_OBJECT,
379 STORE_TRANSITION_SMI_TO_DOUBLE, 379 STORE_TRANSITION_SMI_TO_DOUBLE,
380 STORE_TRANSITION_DOUBLE_TO_OBJECT, 380 STORE_TRANSITION_DOUBLE_TO_OBJECT,
381 STORE_TRANSITION_HOLEY_SMI_TO_OBJECT, 381 STORE_TRANSITION_HOLEY_SMI_TO_OBJECT,
382 STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE, 382 STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE,
383 STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT, 383 STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
384 STORE_AND_GROW_NO_TRANSITION, 384 STORE_AND_GROW_NO_TRANSITION,
385 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT, 385 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
386 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE, 386 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
387 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT, 387 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT,
388 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT, 388 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT,
389 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE, 389 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE,
390 STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT 390 STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT
391 }; 391 };
392 392
393 static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION - 393 static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
394 STORE_NO_TRANSITION; 394 STORE_NO_TRANSITION;
395 STATIC_ASSERT(kGrowICDelta == 395 STATIC_ASSERT(kGrowICDelta ==
396 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT - 396 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
397 STORE_TRANSITION_SMI_TO_OBJECT); 397 STORE_TRANSITION_SMI_TO_OBJECT);
398 STATIC_ASSERT(kGrowICDelta == 398 STATIC_ASSERT(kGrowICDelta ==
399 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE - 399 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
400 STORE_TRANSITION_SMI_TO_DOUBLE); 400 STORE_TRANSITION_SMI_TO_DOUBLE);
401 STATIC_ASSERT(kGrowICDelta == 401 STATIC_ASSERT(kGrowICDelta ==
402 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT - 402 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
403 STORE_TRANSITION_DOUBLE_TO_OBJECT); 403 STORE_TRANSITION_DOUBLE_TO_OBJECT);
404 404
405 explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {} 405 explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
406 virtual ~KeyedIC() {} 406 virtual ~KeyedIC() {}
407 407
408 static inline KeyedAccessGrowMode GetGrowModeFromStubKind( 408 static inline KeyedAccessGrowMode GetGrowModeFromStubKind(
409 StubKind stub_kind) { 409 StubKind stub_kind) {
410 return (stub_kind >= STORE_AND_GROW_NO_TRANSITION) 410 return (stub_kind >= STORE_AND_GROW_NO_TRANSITION)
411 ? ALLOW_JSARRAY_GROWTH 411 ? ALLOW_JSARRAY_GROWTH
412 : DO_NOT_ALLOW_JSARRAY_GROWTH; 412 : DO_NOT_ALLOW_JSARRAY_GROWTH;
413 } 413 }
414 414
415 static inline StubKind GetGrowStubKind(StubKind stub_kind) { 415 static inline StubKind GetGrowStubKind(StubKind stub_kind) {
416 ASSERT(stub_kind != LOAD); 416 ASSERT(stub_kind != LOAD);
417 if (stub_kind < STORE_AND_GROW_NO_TRANSITION) { 417 if (stub_kind < STORE_AND_GROW_NO_TRANSITION) {
418 stub_kind = static_cast<StubKind>(static_cast<int>(stub_kind) + 418 stub_kind = static_cast<StubKind>(static_cast<int>(stub_kind) +
419 kGrowICDelta); 419 kGrowICDelta);
420 } 420 }
421 return stub_kind; 421 return stub_kind;
422 } 422 }
423 423
424 virtual Handle<Code> GetElementStubWithoutMapCheck( 424 virtual Handle<Code> GetElementStubWithoutMapCheck(
425 bool is_js_array, 425 bool is_js_array,
426 ElementsKind elements_kind, 426 ElementsKind elements_kind,
427 KeyedAccessGrowMode grow_mode) = 0; 427 KeyedAccessGrowMode grow_mode) = 0;
428 428
429 protected: 429 protected:
430 virtual Handle<Code> string_stub() { 430 virtual Handle<Code> string_stub() {
431 return Handle<Code>::null(); 431 return Handle<Code>::null();
432 } 432 }
433 433
434 virtual Code::Kind kind() const = 0; 434 virtual Code::Kind kind() const = 0;
435 435
436 Handle<Code> ComputeStub(Handle<JSObject> receiver, 436 Handle<Code> ComputeStub(Handle<JSObject> receiver,
437 StubKind stub_kind, 437 StubKind stub_kind,
438 StrictModeFlag strict_mode, 438 StrictModeFlag strict_mode,
439 Handle<Code> default_stub); 439 Handle<Code> default_stub);
440 440
441 virtual Handle<Code> ComputePolymorphicStub( 441 virtual Handle<Code> ComputePolymorphicStub(
442 MapHandleList* receiver_maps, 442 MapHandleList* receiver_maps,
443 StrictModeFlag strict_mode, 443 StrictModeFlag strict_mode,
444 KeyedAccessGrowMode grow_mode) = 0; 444 KeyedAccessGrowMode grow_mode) = 0;
445 445
446 Handle<Code> ComputeMonomorphicStubWithoutMapCheck( 446 Handle<Code> ComputeMonomorphicStubWithoutMapCheck(
447 Handle<Map> receiver_map, 447 Handle<Map> receiver_map,
448 StrictModeFlag strict_mode, 448 StrictModeFlag strict_mode,
449 KeyedAccessGrowMode grow_mode); 449 KeyedAccessGrowMode grow_mode);
450 450
451 private: 451 private:
452 void GetReceiverMapsForStub(Handle<Code> stub, MapHandleList* result); 452 void GetReceiverMapsForStub(Handle<Code> stub, MapHandleList* result);
453 453
454 Handle<Code> ComputeMonomorphicStub(Handle<Map> receiver_map, 454 Handle<Code> ComputeMonomorphicStub(Handle<Map> receiver_map,
455 StubKind stub_kind, 455 StubKind stub_kind,
456 StrictModeFlag strict_mode, 456 StrictModeFlag strict_mode,
457 Handle<Code> default_stub); 457 Handle<Code> default_stub);
458 458
459 Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver, 459 Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
460 StubKind stub_kind); 460 StubKind stub_kind);
461 461
462 static bool IsTransitionStubKind(StubKind stub_kind) { 462 static bool IsTransitionStubKind(StubKind stub_kind) {
463 return stub_kind > STORE_NO_TRANSITION && 463 return stub_kind > STORE_NO_TRANSITION &&
464 stub_kind != STORE_AND_GROW_NO_TRANSITION; 464 stub_kind != STORE_AND_GROW_NO_TRANSITION;
465 } 465 }
466 466
467 static bool IsGrowStubKind(StubKind stub_kind) { 467 static bool IsGrowStubKind(StubKind stub_kind) {
468 return stub_kind >= STORE_AND_GROW_NO_TRANSITION; 468 return stub_kind >= STORE_AND_GROW_NO_TRANSITION;
469 } 469 }
470 470
471 static StubKind GetNoTransitionStubKind(StubKind stub_kind) { 471 static StubKind GetNoTransitionStubKind(StubKind stub_kind) {
472 if (!IsTransitionStubKind(stub_kind)) return stub_kind; 472 if (!IsTransitionStubKind(stub_kind)) return stub_kind;
473 if (IsGrowStubKind(stub_kind)) return STORE_AND_GROW_NO_TRANSITION; 473 if (IsGrowStubKind(stub_kind)) return STORE_AND_GROW_NO_TRANSITION;
474 return STORE_NO_TRANSITION; 474 return STORE_NO_TRANSITION;
475 } 475 }
476 }; 476 };
477 477
478 478
479 class KeyedLoadIC: public KeyedIC { 479 class KeyedLoadIC: public KeyedIC {
480 public: 480 public:
481 explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) { 481 explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
482 ASSERT(target()->is_keyed_load_stub()); 482 ASSERT(target()->is_keyed_load_stub());
483 } 483 }
484 484
485 MUST_USE_RESULT MaybeObject* Load(State state, 485 MUST_USE_RESULT MaybeObject* Load(State state,
486 Handle<Object> object, 486 Handle<Object> object,
487 Handle<Object> key, 487 Handle<Object> key,
488 bool force_generic_stub); 488 bool force_generic_stub);
489 489
490 // Code generator routines. 490 // Code generator routines.
491 static void GenerateMiss(MacroAssembler* masm, bool force_generic); 491 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
492 static void GenerateRuntimeGetProperty(MacroAssembler* masm); 492 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
493 static void GenerateInitialize(MacroAssembler* masm) { 493 static void GenerateInitialize(MacroAssembler* masm) {
494 GenerateMiss(masm, false); 494 GenerateMiss(masm, false);
495 } 495 }
496 static void GeneratePreMonomorphic(MacroAssembler* masm) { 496 static void GeneratePreMonomorphic(MacroAssembler* masm) {
497 GenerateMiss(masm, false); 497 GenerateMiss(masm, false);
498 } 498 }
499 static void GenerateGeneric(MacroAssembler* masm); 499 static void GenerateGeneric(MacroAssembler* masm);
500 static void GenerateString(MacroAssembler* masm); 500 static void GenerateString(MacroAssembler* masm);
501 static void GenerateIndexedInterceptor(MacroAssembler* masm); 501 static void GenerateIndexedInterceptor(MacroAssembler* masm);
502 static void GenerateNonStrictArguments(MacroAssembler* masm); 502 static void GenerateNonStrictArguments(MacroAssembler* masm);
503 503
504 // Bit mask to be tested against bit field for the cases when 504 // Bit mask to be tested against bit field for the cases when
505 // generic stub should go into slow case. 505 // generic stub should go into slow case.
506 // Access check is necessary explicitly since generic stub does not perform 506 // Access check is necessary explicitly since generic stub does not perform
507 // map checks. 507 // map checks.
508 static const int kSlowCaseBitFieldMask = 508 static const int kSlowCaseBitFieldMask =
509 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); 509 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
510 510
511 virtual Handle<Code> GetElementStubWithoutMapCheck( 511 virtual Handle<Code> GetElementStubWithoutMapCheck(
512 bool is_js_array, 512 bool is_js_array,
513 ElementsKind elements_kind, 513 ElementsKind elements_kind,
514 KeyedAccessGrowMode grow_mode); 514 KeyedAccessGrowMode grow_mode);
515 515
516 virtual bool IsGeneric() const { 516 virtual bool IsGeneric() const {
517 return target() == *generic_stub(); 517 return target() == *generic_stub();
518 } 518 }
519 519
520 protected: 520 protected:
521 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; } 521 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
522 522
523 virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps, 523 virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
524 StrictModeFlag strict_mode, 524 StrictModeFlag strict_mode,
525 KeyedAccessGrowMode grow_mode); 525 KeyedAccessGrowMode grow_mode);
526 526
527 virtual Handle<Code> string_stub() { 527 virtual Handle<Code> string_stub() {
528 return isolate()->builtins()->KeyedLoadIC_String(); 528 return isolate()->builtins()->KeyedLoadIC_String();
529 } 529 }
530 530
531 private: 531 private:
532 // Update the inline cache. 532 // Update the inline cache.
533 void UpdateCaches(LookupResult* lookup, 533 void UpdateCaches(LookupResult* lookup,
534 State state, 534 State state,
535 Handle<Object> object, 535 Handle<Object> object,
536 Handle<String> name); 536 Handle<String> name);
537 537
538 // Stub accessors. 538 // Stub accessors.
539 static Code* initialize_stub() { 539 static Code* initialize_stub() {
540 return Isolate::Current()->builtins()->builtin( 540 return Isolate::Current()->builtins()->builtin(
541 Builtins::kKeyedLoadIC_Initialize); 541 Builtins::kKeyedLoadIC_Initialize);
542 } 542 }
543 Handle<Code> megamorphic_stub() { 543 Handle<Code> megamorphic_stub() {
544 return isolate()->builtins()->KeyedLoadIC_Generic(); 544 return isolate()->builtins()->KeyedLoadIC_Generic();
545 } 545 }
546 Handle<Code> generic_stub() const { 546 Handle<Code> generic_stub() const {
547 return isolate()->builtins()->KeyedLoadIC_Generic(); 547 return isolate()->builtins()->KeyedLoadIC_Generic();
548 } 548 }
549 Handle<Code> pre_monomorphic_stub() { 549 Handle<Code> pre_monomorphic_stub() {
550 return isolate()->builtins()->KeyedLoadIC_PreMonomorphic(); 550 return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
551 } 551 }
552 Handle<Code> indexed_interceptor_stub() { 552 Handle<Code> indexed_interceptor_stub() {
553 return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor(); 553 return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
554 } 554 }
555 Handle<Code> non_strict_arguments_stub() { 555 Handle<Code> non_strict_arguments_stub() {
556 return isolate()->builtins()->KeyedLoadIC_NonStrictArguments(); 556 return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
557 } 557 }
558 558
559 static void Clear(Address address, Code* target); 559 static void Clear(Address address, Code* target);
560 560
561 friend class IC; 561 friend class IC;
562 }; 562 };
563 563
564 564
565 class StoreIC: public IC { 565 class StoreIC: public IC {
566 public: 566 public:
567 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { 567 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
568 ASSERT(target()->is_store_stub()); 568 ASSERT(target()->is_store_stub());
569 } 569 }
570 570
571 MUST_USE_RESULT MaybeObject* Store(State state, 571 MUST_USE_RESULT MaybeObject* Store(State state,
572 StrictModeFlag strict_mode, 572 StrictModeFlag strict_mode,
573 Handle<Object> object, 573 Handle<Object> object,
574 Handle<String> name, 574 Handle<String> name,
575 Handle<Object> value); 575 Handle<Object> value);
576 576
577 // Code generators for stub routines. Only called once at startup. 577 // Code generators for stub routines. Only called once at startup.
578 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } 578 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
579 static void GenerateMiss(MacroAssembler* masm); 579 static void GenerateMiss(MacroAssembler* masm);
580 static void GenerateMegamorphic(MacroAssembler* masm, 580 static void GenerateMegamorphic(MacroAssembler* masm,
581 StrictModeFlag strict_mode); 581 StrictModeFlag strict_mode);
582 static void GenerateArrayLength(MacroAssembler* masm); 582 static void GenerateArrayLength(MacroAssembler* masm);
583 static void GenerateNormal(MacroAssembler* masm); 583 static void GenerateNormal(MacroAssembler* masm);
584 static void GenerateGlobalProxy(MacroAssembler* masm, 584 static void GenerateGlobalProxy(MacroAssembler* masm,
585 StrictModeFlag strict_mode); 585 StrictModeFlag strict_mode);
586 586
587 private: 587 private:
588 // Update the inline cache and the global stub cache based on the 588 // Update the inline cache and the global stub cache based on the
589 // lookup result. 589 // lookup result.
590 void UpdateCaches(LookupResult* lookup, 590 void UpdateCaches(LookupResult* lookup,
591 State state, 591 State state,
592 StrictModeFlag strict_mode, 592 StrictModeFlag strict_mode,
593 Handle<JSObject> receiver, 593 Handle<JSObject> receiver,
594 Handle<String> name, 594 Handle<String> name,
595 Handle<Object> value); 595 Handle<Object> value);
596 596
597 void set_target(Code* code) { 597 void set_target(Code* code) {
598 // Strict mode must be preserved across IC patching. 598 // Strict mode must be preserved across IC patching.
599 ASSERT(Code::GetStrictMode(code->extra_ic_state()) == 599 ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
600 Code::GetStrictMode(target()->extra_ic_state())); 600 Code::GetStrictMode(target()->extra_ic_state()));
601 IC::set_target(code); 601 IC::set_target(code);
602 } 602 }
603 603
604 // Stub accessors. 604 // Stub accessors.
605 Code* megamorphic_stub() { 605 Code* megamorphic_stub() {
606 return isolate()->builtins()->builtin( 606 return isolate()->builtins()->builtin(
607 Builtins::kStoreIC_Megamorphic); 607 Builtins::kStoreIC_Megamorphic);
608 } 608 }
609 Code* megamorphic_stub_strict() { 609 Code* megamorphic_stub_strict() {
610 return isolate()->builtins()->builtin( 610 return isolate()->builtins()->builtin(
611 Builtins::kStoreIC_Megamorphic_Strict); 611 Builtins::kStoreIC_Megamorphic_Strict);
612 } 612 }
613 static Code* initialize_stub() { 613 static Code* initialize_stub() {
614 return Isolate::Current()->builtins()->builtin( 614 return Isolate::Current()->builtins()->builtin(
615 Builtins::kStoreIC_Initialize); 615 Builtins::kStoreIC_Initialize);
616 } 616 }
617 static Code* initialize_stub_strict() { 617 static Code* initialize_stub_strict() {
618 return Isolate::Current()->builtins()->builtin( 618 return Isolate::Current()->builtins()->builtin(
619 Builtins::kStoreIC_Initialize_Strict); 619 Builtins::kStoreIC_Initialize_Strict);
620 } 620 }
621 Handle<Code> global_proxy_stub() { 621 Handle<Code> global_proxy_stub() {
622 return isolate()->builtins()->StoreIC_GlobalProxy(); 622 return isolate()->builtins()->StoreIC_GlobalProxy();
623 } 623 }
624 Handle<Code> global_proxy_stub_strict() { 624 Handle<Code> global_proxy_stub_strict() {
625 return isolate()->builtins()->StoreIC_GlobalProxy_Strict(); 625 return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
626 } 626 }
627 627
628 static void Clear(Address address, Code* target); 628 static void Clear(Address address, Code* target);
629 629
630 friend class IC; 630 friend class IC;
631 }; 631 };
632 632
633 633
634 enum KeyedStoreCheckMap {
635 kDontCheckMap,
636 kCheckMap
637 };
638
639
640 enum KeyedStoreIncrementLength {
641 kDontIncrementLength,
642 kIncrementLength
643 };
644
645
634 class KeyedStoreIC: public KeyedIC { 646 class KeyedStoreIC: public KeyedIC {
635 public: 647 public:
636 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) { 648 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
637 ASSERT(target()->is_keyed_store_stub()); 649 ASSERT(target()->is_keyed_store_stub());
638 } 650 }
639 651
640 MUST_USE_RESULT MaybeObject* Store(State state, 652 MUST_USE_RESULT MaybeObject* Store(State state,
641 StrictModeFlag strict_mode, 653 StrictModeFlag strict_mode,
642 Handle<Object> object, 654 Handle<Object> object,
643 Handle<Object> name, 655 Handle<Object> name,
644 Handle<Object> value, 656 Handle<Object> value,
645 bool force_generic); 657 bool force_generic);
646 658
647 // Code generators for stub routines. Only called once at startup. 659 // Code generators for stub routines. Only called once at startup.
648 static void GenerateInitialize(MacroAssembler* masm) { 660 static void GenerateInitialize(MacroAssembler* masm) {
649 GenerateMiss(masm, false); 661 GenerateMiss(masm, false);
650 } 662 }
651 static void GenerateMiss(MacroAssembler* masm, bool force_generic); 663 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
652 static void GenerateSlow(MacroAssembler* masm); 664 static void GenerateSlow(MacroAssembler* masm);
653 static void GenerateRuntimeSetProperty(MacroAssembler* masm, 665 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
654 StrictModeFlag strict_mode); 666 StrictModeFlag strict_mode);
655 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode); 667 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
656 static void GenerateNonStrictArguments(MacroAssembler* masm); 668 static void GenerateNonStrictArguments(MacroAssembler* masm);
657 static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm); 669 static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm);
658 static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm); 670 static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm);
659 671
660 virtual Handle<Code> GetElementStubWithoutMapCheck( 672 virtual Handle<Code> GetElementStubWithoutMapCheck(
661 bool is_js_array, 673 bool is_js_array,
662 ElementsKind elements_kind, 674 ElementsKind elements_kind,
663 KeyedAccessGrowMode grow_mode); 675 KeyedAccessGrowMode grow_mode);
664 676
665 virtual bool IsGeneric() const { 677 virtual bool IsGeneric() const {
666 return target() == *generic_stub() || 678 return target() == *generic_stub() ||
667 target() == *generic_stub_strict(); 679 target() == *generic_stub_strict();
668 } 680 }
669 681
670 protected: 682 protected:
671 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; } 683 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
672 684
673 virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps, 685 virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
674 StrictModeFlag strict_mode, 686 StrictModeFlag strict_mode,
675 KeyedAccessGrowMode grow_mode); 687 KeyedAccessGrowMode grow_mode);
676 688
677 private: 689 private:
678 // Update the inline cache. 690 // Update the inline cache.
679 void UpdateCaches(LookupResult* lookup, 691 void UpdateCaches(LookupResult* lookup,
680 State state, 692 State state,
681 StrictModeFlag strict_mode, 693 StrictModeFlag strict_mode,
682 Handle<JSObject> receiver, 694 Handle<JSObject> receiver,
683 Handle<String> name, 695 Handle<String> name,
684 Handle<Object> value); 696 Handle<Object> value);
685 697
686 void set_target(Code* code) { 698 void set_target(Code* code) {
687 // Strict mode must be preserved across IC patching. 699 // Strict mode must be preserved across IC patching.
688 ASSERT(Code::GetStrictMode(code->extra_ic_state()) == 700 ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
689 Code::GetStrictMode(target()->extra_ic_state())); 701 Code::GetStrictMode(target()->extra_ic_state()));
690 IC::set_target(code); 702 IC::set_target(code);
691 } 703 }
692 704
693 // Stub accessors. 705 // Stub accessors.
694 static Code* initialize_stub() { 706 static Code* initialize_stub() {
695 return Isolate::Current()->builtins()->builtin( 707 return Isolate::Current()->builtins()->builtin(
696 Builtins::kKeyedStoreIC_Initialize); 708 Builtins::kKeyedStoreIC_Initialize);
697 } 709 }
698 static Code* initialize_stub_strict() { 710 static Code* initialize_stub_strict() {
699 return Isolate::Current()->builtins()->builtin( 711 return Isolate::Current()->builtins()->builtin(
700 Builtins::kKeyedStoreIC_Initialize_Strict); 712 Builtins::kKeyedStoreIC_Initialize_Strict);
701 } 713 }
702 Handle<Code> megamorphic_stub() { 714 Handle<Code> megamorphic_stub() {
703 return isolate()->builtins()->KeyedStoreIC_Generic(); 715 return isolate()->builtins()->KeyedStoreIC_Generic();
704 } 716 }
705 Handle<Code> megamorphic_stub_strict() { 717 Handle<Code> megamorphic_stub_strict() {
706 return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); 718 return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
707 } 719 }
708 Handle<Code> generic_stub() const { 720 Handle<Code> generic_stub() const {
709 return isolate()->builtins()->KeyedStoreIC_Generic(); 721 return isolate()->builtins()->KeyedStoreIC_Generic();
710 } 722 }
711 Handle<Code> generic_stub_strict() const { 723 Handle<Code> generic_stub_strict() const {
712 return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); 724 return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
713 } 725 }
714 Handle<Code> non_strict_arguments_stub() { 726 Handle<Code> non_strict_arguments_stub() {
715 return isolate()->builtins()->KeyedStoreIC_NonStrictArguments(); 727 return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
716 } 728 }
717 729
718 static void Clear(Address address, Code* target); 730 static void Clear(Address address, Code* target);
719 731
720 StubKind GetStubKind(Handle<JSObject> receiver, 732 StubKind GetStubKind(Handle<JSObject> receiver,
721 Handle<Object> key, 733 Handle<Object> key,
722 Handle<Object> value); 734 Handle<Object> value);
723 735
724 friend class IC; 736 friend class IC;
725 }; 737 };
726 738
727 739
728 class UnaryOpIC: public IC { 740 class UnaryOpIC: public IC {
729 public: 741 public:
730 // sorted: increasingly more unspecific (ignoring UNINITIALIZED) 742 // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
731 // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead. 743 // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
732 enum TypeInfo { 744 enum TypeInfo {
733 UNINITIALIZED, 745 UNINITIALIZED,
734 SMI, 746 SMI,
735 HEAP_NUMBER, 747 HEAP_NUMBER,
736 GENERIC 748 GENERIC
737 }; 749 };
738 750
739 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { } 751 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
740 752
741 void patch(Code* code); 753 void patch(Code* code);
742 754
743 static const char* GetName(TypeInfo type_info); 755 static const char* GetName(TypeInfo type_info);
744 756
745 static State ToState(TypeInfo type_info); 757 static State ToState(TypeInfo type_info);
746 758
747 static TypeInfo GetTypeInfo(Handle<Object> operand); 759 static TypeInfo GetTypeInfo(Handle<Object> operand);
748 760
749 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous); 761 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
750 }; 762 };
751 763
752 764
753 // Type Recording BinaryOpIC, that records the types of the inputs and outputs. 765 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
754 class BinaryOpIC: public IC { 766 class BinaryOpIC: public IC {
755 public: 767 public:
756 enum TypeInfo { 768 enum TypeInfo {
757 UNINITIALIZED, 769 UNINITIALIZED,
758 SMI, 770 SMI,
759 INT32, 771 INT32,
760 HEAP_NUMBER, 772 HEAP_NUMBER,
761 ODDBALL, 773 ODDBALL,
762 BOTH_STRING, // Only used for addition operation. 774 BOTH_STRING, // Only used for addition operation.
763 STRING, // Only used for addition operation. At least one string operand. 775 STRING, // Only used for addition operation. At least one string operand.
764 GENERIC 776 GENERIC
765 }; 777 };
766 778
767 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { } 779 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
768 780
769 void patch(Code* code); 781 void patch(Code* code);
770 782
771 static const char* GetName(TypeInfo type_info); 783 static const char* GetName(TypeInfo type_info);
772 784
773 static State ToState(TypeInfo type_info); 785 static State ToState(TypeInfo type_info);
774 786
775 static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right); 787 static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
776 788
777 static TypeInfo JoinTypes(TypeInfo x, TypeInfo y); 789 static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
778 }; 790 };
779 791
780 792
781 class CompareIC: public IC { 793 class CompareIC: public IC {
782 public: 794 public:
783 enum State { 795 enum State {
784 UNINITIALIZED, 796 UNINITIALIZED,
785 SMIS, 797 SMIS,
786 HEAP_NUMBERS, 798 HEAP_NUMBERS,
787 SYMBOLS, 799 SYMBOLS,
788 STRINGS, 800 STRINGS,
789 OBJECTS, 801 OBJECTS,
790 KNOWN_OBJECTS, 802 KNOWN_OBJECTS,
791 GENERIC 803 GENERIC
792 }; 804 };
793 805
794 CompareIC(Isolate* isolate, Token::Value op) 806 CompareIC(Isolate* isolate, Token::Value op)
795 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { } 807 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
796 808
797 // Update the inline cache for the given operands. 809 // Update the inline cache for the given operands.
798 void UpdateCaches(Handle<Object> x, Handle<Object> y); 810 void UpdateCaches(Handle<Object> x, Handle<Object> y);
799 811
800 // Factory method for getting an uninitialized compare stub. 812 // Factory method for getting an uninitialized compare stub.
801 static Handle<Code> GetUninitialized(Token::Value op); 813 static Handle<Code> GetUninitialized(Token::Value op);
802 814
803 // Helper function for computing the condition for a compare operation. 815 // Helper function for computing the condition for a compare operation.
804 static Condition ComputeCondition(Token::Value op); 816 static Condition ComputeCondition(Token::Value op);
805 817
806 // Helper function for determining the state of a compare IC. 818 // Helper function for determining the state of a compare IC.
807 static State ComputeState(Code* target); 819 static State ComputeState(Code* target);
808 820
809 // Helper function for determining the operation a compare IC is for. 821 // Helper function for determining the operation a compare IC is for.
810 static Token::Value ComputeOperation(Code* target); 822 static Token::Value ComputeOperation(Code* target);
811 823
812 static const char* GetStateName(State state); 824 static const char* GetStateName(State state);
813 825
814 private: 826 private:
815 State TargetState(State state, bool has_inlined_smi_code, 827 State TargetState(State state, bool has_inlined_smi_code,
816 Handle<Object> x, Handle<Object> y); 828 Handle<Object> x, Handle<Object> y);
817 829
818 bool strict() const { return op_ == Token::EQ_STRICT; } 830 bool strict() const { return op_ == Token::EQ_STRICT; }
819 Condition GetCondition() const { return ComputeCondition(op_); } 831 Condition GetCondition() const { return ComputeCondition(op_); }
820 State GetState() { return ComputeState(target()); } 832 State GetState() { return ComputeState(target()); }
821 833
822 static Code* GetRawUninitialized(Token::Value op); 834 static Code* GetRawUninitialized(Token::Value op);
823 835
824 static void Clear(Address address, Code* target); 836 static void Clear(Address address, Code* target);
825 837
826 Token::Value op_; 838 Token::Value op_;
827 839
828 friend class IC; 840 friend class IC;
829 }; 841 };
830 842
831 843
832 class ToBooleanIC: public IC { 844 class ToBooleanIC: public IC {
833 public: 845 public:
834 explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { } 846 explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
835 847
836 void patch(Code* code); 848 void patch(Code* code);
837 }; 849 };
838 850
839 851
840 // Helper for BinaryOpIC and CompareIC. 852 // Helper for BinaryOpIC and CompareIC.
841 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; 853 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
842 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); 854 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
843 855
844 } } // namespace v8::internal 856 } } // namespace v8::internal
845 857
846 #endif // V8_IC_H_ 858 #endif // V8_IC_H_
Powered by Google Project Hosting