blob: ece5be9f05002df7b19da88e0f9aad29c41a4174 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
28#ifndef V8_IC_H_
29#define V8_IC_H_
30
Ben Murdochb0fe1622011-05-05 13:52:32 +010031#include "macro-assembler.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000032#include "type-info.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033
34namespace v8 {
35namespace internal {
36
Leon Clarkee46be812010-01-19 14:06:41 +000037
Steve Blocka7e24c12009-10-30 11:49:00 +000038// IC_UTIL_LIST defines all utility functions called from generated
39// inline caching code. The argument for the macro, ICU, is the function name.
40#define IC_UTIL_LIST(ICU) \
41 ICU(LoadIC_Miss) \
42 ICU(KeyedLoadIC_Miss) \
Ben Murdoch257744e2011-11-30 15:57:28 +000043 ICU(KeyedLoadIC_MissForceGeneric) \
Steve Blocka7e24c12009-10-30 11:49:00 +000044 ICU(CallIC_Miss) \
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010045 ICU(KeyedCallIC_Miss) \
Steve Blocka7e24c12009-10-30 11:49:00 +000046 ICU(StoreIC_Miss) \
Steve Block6ded16b2010-05-10 14:33:55 +010047 ICU(StoreIC_ArrayLength) \
Steve Blocka7e24c12009-10-30 11:49:00 +000048 ICU(SharedStoreIC_ExtendStorage) \
49 ICU(KeyedStoreIC_Miss) \
Ben Murdoch257744e2011-11-30 15:57:28 +000050 ICU(KeyedStoreIC_MissForceGeneric) \
51 ICU(KeyedStoreIC_Slow) \
Steve Blocka7e24c12009-10-30 11:49:00 +000052 /* Utilities for IC stubs. */ \
53 ICU(LoadCallbackProperty) \
54 ICU(StoreCallbackProperty) \
55 ICU(LoadPropertyWithInterceptorOnly) \
56 ICU(LoadPropertyWithInterceptorForLoad) \
57 ICU(LoadPropertyWithInterceptorForCall) \
Andrei Popescu402d9372010-02-26 13:31:12 +000058 ICU(KeyedLoadPropertyWithInterceptor) \
Steve Block6ded16b2010-05-10 14:33:55 +010059 ICU(StoreInterceptorProperty) \
Ben Murdoch257744e2011-11-30 15:57:28 +000060 ICU(UnaryOp_Patch) \
61 ICU(BinaryOp_Patch) \
Ben Murdoch69a99ed2011-11-30 16:03:39 +000062 ICU(CompareIC_Miss) \
63 ICU(ToBoolean_Patch)
Steve Blocka7e24c12009-10-30 11:49:00 +000064//
65// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
66// and KeyedStoreIC.
67//
68class IC {
69 public:
Steve Blocka7e24c12009-10-30 11:49:00 +000070 // The ids for utility called from the generated code.
71 enum UtilityId {
72 #define CONST_NAME(name) k##name,
73 IC_UTIL_LIST(CONST_NAME)
74 #undef CONST_NAME
75 kUtilityCount
76 };
77
78 // Looks up the address of the named utility.
79 static Address AddressFromUtilityId(UtilityId id);
80
81 // Alias the inline cache state type to make the IC code more readable.
82 typedef InlineCacheState State;
83
84 // The IC code is either invoked with no extra frames on the stack
85 // or with a single extra frame for supporting calls.
86 enum FrameDepth {
87 NO_EXTRA_FRAME = 0,
88 EXTRA_CALL_FRAME = 1
89 };
90
91 // Construct the IC structure with the given number of extra
92 // JavaScript frames on the stack.
Steve Block44f0eee2011-05-26 01:26:41 +010093 IC(FrameDepth depth, Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000094
95 // Get the call-site target; used for determining the state.
96 Code* target() { return GetTargetAtAddress(address()); }
97 inline Address address();
98
Steve Block6ded16b2010-05-10 14:33:55 +010099 // Compute the current IC state based on the target stub, receiver and name.
100 static State StateFrom(Code* target, Object* receiver, Object* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000101
102 // Clear the inline cache to initial state.
103 static void Clear(Address address);
104
105 // Computes the reloc info for this IC. This is a fairly expensive
106 // operation as it has to search through the heap to find the code
107 // object that contains this IC site.
108 RelocInfo::Mode ComputeMode();
109
110 // Returns if this IC is for contextual (no explicit receiver)
111 // access to properties.
Leon Clarkee46be812010-01-19 14:06:41 +0000112 bool IsContextual(Handle<Object> receiver) {
113 if (receiver->IsGlobalObject()) {
114 return SlowIsContextual();
115 } else {
116 ASSERT(!SlowIsContextual());
117 return false;
118 }
119 }
120
121 bool SlowIsContextual() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
123 }
124
Steve Block8defd9f2010-07-08 12:39:36 +0100125 // Determines which map must be used for keeping the code stub.
126 // These methods should not be called with undefined or null.
127 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
128 JSObject* holder);
129 static inline InlineCacheHolderFlag GetCodeCacheForObject(JSObject* object,
130 JSObject* holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100131 static inline JSObject* GetCodeCacheHolder(Object* object,
132 InlineCacheHolderFlag holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
134 protected:
135 Address fp() const { return fp_; }
136 Address pc() const { return *pc_address_; }
Steve Block44f0eee2011-05-26 01:26:41 +0100137 Isolate* isolate() const { return isolate_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000138
139#ifdef ENABLE_DEBUGGER_SUPPORT
140 // Computes the address in the original code when the code running is
141 // containing break points (calls to DebugBreakXXX builtins).
142 Address OriginalCodeAddress();
143#endif
144
145 // Set the call-site target.
146 void set_target(Code* code) { SetTargetAtAddress(address(), code); }
147
148#ifdef DEBUG
Ben Murdoch257744e2011-11-30 15:57:28 +0000149 void TraceIC(const char* type,
150 Handle<Object> name,
151 State old_state,
Ben Murdoch589d6972011-11-30 16:04:58 +0000152 Code* new_target);
Steve Blocka7e24c12009-10-30 11:49:00 +0000153#endif
154
Steve Block44f0eee2011-05-26 01:26:41 +0100155 Failure* TypeError(const char* type,
156 Handle<Object> object,
157 Handle<Object> key);
158 Failure* ReferenceError(const char* type, Handle<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000159
160 // Access the target code for the given IC address.
161 static inline Code* GetTargetAtAddress(Address address);
162 static inline void SetTargetAtAddress(Address address, Code* target);
163
164 private:
165 // Frame pointer for the frame that uses (calls) the IC.
166 Address fp_;
167
168 // All access to the program counter of an IC structure is indirect
169 // to make the code GC safe. This feature is crucial since
170 // GetProperty and SetProperty are called and they in turn might
171 // invoke the garbage collector.
172 Address* pc_address_;
173
Steve Block44f0eee2011-05-26 01:26:41 +0100174 Isolate* isolate_;
175
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
177};
178
179
180// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
181// cannot make forward declarations to an enum.
182class IC_Utility {
183 public:
184 explicit IC_Utility(IC::UtilityId id)
185 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
186
187 Address address() const { return address_; }
188
189 IC::UtilityId id() const { return id_; }
190 private:
191 Address address_;
192 IC::UtilityId id_;
193};
194
195
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100196class CallICBase: public IC {
Ben Murdoch257744e2011-11-30 15:57:28 +0000197 public:
198 class Contextual: public BitField<bool, 0, 1> {};
199 class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
200
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100201 protected:
Steve Block44f0eee2011-05-26 01:26:41 +0100202 CallICBase(Code::Kind kind, Isolate* isolate)
203 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000204
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100205 public:
John Reck59135872010-11-02 12:39:01 -0700206 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100207 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700208 Handle<Object> object,
209 Handle<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000210
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100211 protected:
212 Code::Kind kind_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000213
Ben Murdochb8e0da22011-05-16 14:20:40 +0100214 bool TryUpdateExtraICState(LookupResult* lookup,
215 Handle<Object> object,
216 Code::ExtraICState* extra_ic_state);
217
218 MUST_USE_RESULT MaybeObject* ComputeMonomorphicStub(
219 LookupResult* lookup,
220 State state,
221 Code::ExtraICState extra_ic_state,
222 Handle<Object> object,
223 Handle<String> name);
224
Steve Blocka7e24c12009-10-30 11:49:00 +0000225 // Update the inline cache and the global stub cache based on the
226 // lookup result.
227 void UpdateCaches(LookupResult* lookup,
228 State state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100229 Code::ExtraICState extra_ic_state,
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 Handle<Object> object,
231 Handle<String> name);
232
233 // Returns a JSFunction if the object can be called as a function,
234 // and patches the stack to be ready for the call.
235 // Otherwise, it returns the undefined value.
236 Object* TryCallAsFunction(Object* object);
237
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100238 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
Leon Clarkee46be812010-01-19 14:06:41 +0000239
Steve Blocka7e24c12009-10-30 11:49:00 +0000240 static void Clear(Address address, Code* target);
Ben Murdoch257744e2011-11-30 15:57:28 +0000241
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 friend class IC;
243};
244
245
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100246class CallIC: public CallICBase {
247 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100248 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
249 ASSERT(target()->is_call_stub());
250 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100251
252 // Code generator routines.
Ben Murdoch257744e2011-11-30 15:57:28 +0000253 static void GenerateInitialize(MacroAssembler* masm,
254 int argc,
255 Code::ExtraICState extra_ic_state) {
256 GenerateMiss(masm, argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100257 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000258 static void GenerateMiss(MacroAssembler* masm,
259 int argc,
260 Code::ExtraICState extra_ic_state);
261 static void GenerateMegamorphic(MacroAssembler* masm,
262 int argc,
263 Code::ExtraICState extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100264 static void GenerateNormal(MacroAssembler* masm, int argc);
265};
266
267
268class KeyedCallIC: public CallICBase {
269 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100270 explicit KeyedCallIC(Isolate* isolate)
271 : CallICBase(Code::KEYED_CALL_IC, isolate) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100272 ASSERT(target()->is_keyed_call_stub());
273 }
274
John Reck59135872010-11-02 12:39:01 -0700275 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
276 Handle<Object> object,
277 Handle<Object> key);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100278
279 // Code generator routines.
280 static void GenerateInitialize(MacroAssembler* masm, int argc) {
281 GenerateMiss(masm, argc);
282 }
283 static void GenerateMiss(MacroAssembler* masm, int argc);
284 static void GenerateMegamorphic(MacroAssembler* masm, int argc);
285 static void GenerateNormal(MacroAssembler* masm, int argc);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000286 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100287};
288
289
Steve Blocka7e24c12009-10-30 11:49:00 +0000290class LoadIC: public IC {
291 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100292 explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
293 ASSERT(target()->is_load_stub());
294 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000295
John Reck59135872010-11-02 12:39:01 -0700296 MUST_USE_RESULT MaybeObject* Load(State state,
297 Handle<Object> object,
298 Handle<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000299
300 // Code generator routines.
Andrei Popescu402d9372010-02-26 13:31:12 +0000301 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
302 static void GeneratePreMonomorphic(MacroAssembler* masm) {
303 GenerateMiss(masm);
304 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 static void GenerateMiss(MacroAssembler* masm);
306 static void GenerateMegamorphic(MacroAssembler* masm);
307 static void GenerateNormal(MacroAssembler* masm);
308
309 // Specialized code generator routines.
310 static void GenerateArrayLength(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100311 static void GenerateStringLength(MacroAssembler* masm,
312 bool support_wrappers);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 static void GenerateFunctionPrototype(MacroAssembler* masm);
314
Steve Blocka7e24c12009-10-30 11:49:00 +0000315 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 // Update the inline cache and the global stub cache based on the
317 // lookup result.
318 void UpdateCaches(LookupResult* lookup,
319 State state,
320 Handle<Object> object,
321 Handle<String> name);
322
323 // Stub accessors.
Steve Block44f0eee2011-05-26 01:26:41 +0100324 Code* megamorphic_stub() {
325 return isolate()->builtins()->builtin(
326 Builtins::kLoadIC_Megamorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 }
328 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100329 return Isolate::Current()->builtins()->builtin(
330 Builtins::kLoadIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000331 }
Steve Block44f0eee2011-05-26 01:26:41 +0100332 Code* pre_monomorphic_stub() {
333 return isolate()->builtins()->builtin(
334 Builtins::kLoadIC_PreMonomorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000335 }
336
337 static void Clear(Address address, Code* target);
338
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 friend class IC;
340};
341
342
Ben Murdoch257744e2011-11-30 15:57:28 +0000343class KeyedIC: public IC {
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000345 explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
346 virtual ~KeyedIC() {}
347
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000348 virtual MaybeObject* GetElementStubWithoutMapCheck(
349 bool is_js_array,
Ben Murdoch589d6972011-11-30 16:04:58 +0000350 ElementsKind elements_kind) = 0;
Ben Murdoch257744e2011-11-30 15:57:28 +0000351
352 protected:
353 virtual Code* string_stub() {
354 return NULL;
355 }
356
357 virtual Code::Kind kind() const = 0;
358
Ben Murdoch257744e2011-11-30 15:57:28 +0000359 MaybeObject* ComputeStub(JSObject* receiver,
360 bool is_store,
361 StrictModeFlag strict_mode,
362 Code* default_stub);
363
364 virtual MaybeObject* ConstructMegamorphicStub(
365 MapList* receiver_maps,
366 CodeList* targets,
367 StrictModeFlag strict_mode) = 0;
368
369 private:
370 void GetReceiverMapsForStub(Code* stub, MapList* result);
371
372 MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
373 Map* receiver_map,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000374 StrictModeFlag strict_mode);
Ben Murdoch257744e2011-11-30 15:57:28 +0000375
376 MaybeObject* ComputeMonomorphicStub(JSObject* receiver,
377 bool is_store,
378 StrictModeFlag strict_mode,
379 Code* default_stub);
380};
381
382
383class KeyedLoadIC: public KeyedIC {
384 public:
385 explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +0100386 ASSERT(target()->is_keyed_load_stub());
387 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000388
John Reck59135872010-11-02 12:39:01 -0700389 MUST_USE_RESULT MaybeObject* Load(State state,
390 Handle<Object> object,
Ben Murdoch257744e2011-11-30 15:57:28 +0000391 Handle<Object> key,
392 bool force_generic_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000393
394 // Code generator routines.
Ben Murdoch257744e2011-11-30 15:57:28 +0000395 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
Andrei Popescu402d9372010-02-26 13:31:12 +0000396 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000397 static void GenerateInitialize(MacroAssembler* masm) {
398 GenerateMiss(masm, false);
399 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000400 static void GeneratePreMonomorphic(MacroAssembler* masm) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000401 GenerateMiss(masm, false);
Andrei Popescu402d9372010-02-26 13:31:12 +0000402 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 static void GenerateGeneric(MacroAssembler* masm);
Leon Clarkee46be812010-01-19 14:06:41 +0000404 static void GenerateString(MacroAssembler* masm);
Andrei Popescu402d9372010-02-26 13:31:12 +0000405 static void GenerateIndexedInterceptor(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000406 static void GenerateNonStrictArguments(MacroAssembler* masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000407
Leon Clarked91b9f72010-01-27 17:25:45 +0000408 // Bit mask to be tested against bit field for the cases when
409 // generic stub should go into slow case.
410 // Access check is necessary explicitly since generic stub does not perform
411 // map checks.
412 static const int kSlowCaseBitFieldMask =
413 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
414
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000415 virtual MaybeObject* GetElementStubWithoutMapCheck(
416 bool is_js_array,
Ben Murdoch589d6972011-11-30 16:04:58 +0000417 ElementsKind elements_kind);
Ben Murdoch257744e2011-11-30 15:57:28 +0000418
419 protected:
420 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
421
Ben Murdoch257744e2011-11-30 15:57:28 +0000422 virtual MaybeObject* ConstructMegamorphicStub(
423 MapList* receiver_maps,
424 CodeList* targets,
425 StrictModeFlag strict_mode);
426
427 virtual Code* string_stub() {
428 return isolate()->builtins()->builtin(
429 Builtins::kKeyedLoadIC_String);
430 }
431
Steve Block6ded16b2010-05-10 14:33:55 +0100432 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 // Update the inline cache.
434 void UpdateCaches(LookupResult* lookup,
435 State state,
436 Handle<Object> object,
437 Handle<String> name);
438
439 // Stub accessors.
440 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100441 return Isolate::Current()->builtins()->builtin(
442 Builtins::kKeyedLoadIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 }
Steve Block44f0eee2011-05-26 01:26:41 +0100444 Code* megamorphic_stub() {
445 return isolate()->builtins()->builtin(
446 Builtins::kKeyedLoadIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000447 }
Steve Block44f0eee2011-05-26 01:26:41 +0100448 Code* generic_stub() {
449 return isolate()->builtins()->builtin(
450 Builtins::kKeyedLoadIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 }
Steve Block44f0eee2011-05-26 01:26:41 +0100452 Code* pre_monomorphic_stub() {
453 return isolate()->builtins()->builtin(
454 Builtins::kKeyedLoadIC_PreMonomorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 }
Steve Block44f0eee2011-05-26 01:26:41 +0100456 Code* indexed_interceptor_stub() {
457 return isolate()->builtins()->builtin(
458 Builtins::kKeyedLoadIC_IndexedInterceptor);
Andrei Popescu402d9372010-02-26 13:31:12 +0000459 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000460 Code* non_strict_arguments_stub() {
461 return isolate()->builtins()->builtin(
462 Builtins::kKeyedLoadIC_NonStrictArguments);
463 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000464
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 static void Clear(Address address, Code* target);
466
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 friend class IC;
468};
469
470
471class StoreIC: public IC {
472 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100473 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
474 ASSERT(target()->is_store_stub());
475 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000476
John Reck59135872010-11-02 12:39:01 -0700477 MUST_USE_RESULT MaybeObject* Store(State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100478 StrictModeFlag strict_mode,
John Reck59135872010-11-02 12:39:01 -0700479 Handle<Object> object,
480 Handle<String> name,
481 Handle<Object> value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000482
483 // Code generators for stub routines. Only called once at startup.
Leon Clarke4515c472010-02-03 11:58:03 +0000484 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 static void GenerateMiss(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100486 static void GenerateMegamorphic(MacroAssembler* masm,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100487 StrictModeFlag strict_mode);
Steve Block6ded16b2010-05-10 14:33:55 +0100488 static void GenerateArrayLength(MacroAssembler* masm);
Steve Block8defd9f2010-07-08 12:39:36 +0100489 static void GenerateNormal(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100490 static void GenerateGlobalProxy(MacroAssembler* masm,
491 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000492
493 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 // Update the inline cache and the global stub cache based on the
495 // lookup result.
496 void UpdateCaches(LookupResult* lookup,
Steve Block1e0659c2011-05-24 12:43:12 +0100497 State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100498 StrictModeFlag strict_mode,
Steve Block1e0659c2011-05-24 12:43:12 +0100499 Handle<JSObject> receiver,
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 Handle<String> name,
501 Handle<Object> value);
502
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100503 void set_target(Code* code) {
504 // Strict mode must be preserved across IC patching.
505 ASSERT((code->extra_ic_state() & kStrictMode) ==
506 (target()->extra_ic_state() & kStrictMode));
507 IC::set_target(code);
508 }
509
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 // Stub accessors.
Steve Block44f0eee2011-05-26 01:26:41 +0100511 Code* megamorphic_stub() {
512 return isolate()->builtins()->builtin(
513 Builtins::kStoreIC_Megamorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 }
Steve Block44f0eee2011-05-26 01:26:41 +0100515 Code* megamorphic_stub_strict() {
516 return isolate()->builtins()->builtin(
517 Builtins::kStoreIC_Megamorphic_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100518 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000519 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100520 return Isolate::Current()->builtins()->builtin(
521 Builtins::kStoreIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000522 }
Steve Block1e0659c2011-05-24 12:43:12 +0100523 static Code* initialize_stub_strict() {
Steve Block44f0eee2011-05-26 01:26:41 +0100524 return Isolate::Current()->builtins()->builtin(
525 Builtins::kStoreIC_Initialize_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100526 }
Steve Block44f0eee2011-05-26 01:26:41 +0100527 Code* global_proxy_stub() {
528 return isolate()->builtins()->builtin(
529 Builtins::kStoreIC_GlobalProxy);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100530 }
Steve Block44f0eee2011-05-26 01:26:41 +0100531 Code* global_proxy_stub_strict() {
532 return isolate()->builtins()->builtin(
533 Builtins::kStoreIC_GlobalProxy_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100534 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000535
536 static void Clear(Address address, Code* target);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100537
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 friend class IC;
539};
540
541
Ben Murdoch257744e2011-11-30 15:57:28 +0000542class KeyedStoreIC: public KeyedIC {
Steve Blocka7e24c12009-10-30 11:49:00 +0000543 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000544 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
545 ASSERT(target()->is_keyed_store_stub());
546 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000547
John Reck59135872010-11-02 12:39:01 -0700548 MUST_USE_RESULT MaybeObject* Store(State state,
Ben Murdoch257744e2011-11-30 15:57:28 +0000549 StrictModeFlag strict_mode,
John Reck59135872010-11-02 12:39:01 -0700550 Handle<Object> object,
551 Handle<Object> name,
Ben Murdoch257744e2011-11-30 15:57:28 +0000552 Handle<Object> value,
553 bool force_generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000554
555 // Code generators for stub routines. Only called once at startup.
Ben Murdoch257744e2011-11-30 15:57:28 +0000556 static void GenerateInitialize(MacroAssembler* masm) {
557 GenerateMiss(masm, false);
558 }
559 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
560 static void GenerateSlow(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100561 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
562 StrictModeFlag strict_mode);
563 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000564 static void GenerateNonStrictArguments(MacroAssembler* masm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000565
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000566 virtual MaybeObject* GetElementStubWithoutMapCheck(
567 bool is_js_array,
Ben Murdoch589d6972011-11-30 16:04:58 +0000568 ElementsKind elements_kind);
Steve Block053d10c2011-06-13 19:13:29 +0100569
Ben Murdoch257744e2011-11-30 15:57:28 +0000570 protected:
571 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
572
Ben Murdoch257744e2011-11-30 15:57:28 +0000573 virtual MaybeObject* ConstructMegamorphicStub(
574 MapList* receiver_maps,
575 CodeList* targets,
576 StrictModeFlag strict_mode);
577
578 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000579 // Update the inline cache.
580 void UpdateCaches(LookupResult* lookup,
581 State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100582 StrictModeFlag strict_mode,
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 Handle<JSObject> receiver,
584 Handle<String> name,
585 Handle<Object> value);
586
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100587 void set_target(Code* code) {
588 // Strict mode must be preserved across IC patching.
589 ASSERT((code->extra_ic_state() & kStrictMode) ==
590 (target()->extra_ic_state() & kStrictMode));
591 IC::set_target(code);
592 }
593
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 // Stub accessors.
595 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100596 return Isolate::Current()->builtins()->builtin(
597 Builtins::kKeyedStoreIC_Initialize);
598 }
599 Code* megamorphic_stub() {
600 return isolate()->builtins()->builtin(
601 Builtins::kKeyedStoreIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000602 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100603 static Code* initialize_stub_strict() {
Steve Block44f0eee2011-05-26 01:26:41 +0100604 return Isolate::Current()->builtins()->builtin(
605 Builtins::kKeyedStoreIC_Initialize_Strict);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100606 }
Steve Block44f0eee2011-05-26 01:26:41 +0100607 Code* megamorphic_stub_strict() {
608 return isolate()->builtins()->builtin(
609 Builtins::kKeyedStoreIC_Generic_Strict);
Steve Blocka7e24c12009-10-30 11:49:00 +0000610 }
Steve Block44f0eee2011-05-26 01:26:41 +0100611 Code* generic_stub() {
612 return isolate()->builtins()->builtin(
613 Builtins::kKeyedStoreIC_Generic);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100614 }
Steve Block44f0eee2011-05-26 01:26:41 +0100615 Code* generic_stub_strict() {
616 return isolate()->builtins()->builtin(
617 Builtins::kKeyedStoreIC_Generic_Strict);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100618 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000619 Code* non_strict_arguments_stub() {
620 return isolate()->builtins()->builtin(
621 Builtins::kKeyedStoreIC_NonStrictArguments);
622 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000623
624 static void Clear(Address address, Code* target);
625
Steve Blocka7e24c12009-10-30 11:49:00 +0000626 friend class IC;
627};
628
629
Ben Murdoch257744e2011-11-30 15:57:28 +0000630class UnaryOpIC: public IC {
631 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000632 // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
633 // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
634 enum TypeInfo {
635 UNINITIALIZED,
636 SMI,
637 HEAP_NUMBER,
638 GENERIC
639 };
640
641 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
642
643 void patch(Code* code);
644
645 static const char* GetName(TypeInfo type_info);
646
647 static State ToState(TypeInfo type_info);
648
649 static TypeInfo GetTypeInfo(Handle<Object> operand);
650
651 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
652};
653
654
Ben Murdochb0fe1622011-05-05 13:52:32 +0100655// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
Ben Murdoch257744e2011-11-30 15:57:28 +0000656class BinaryOpIC: public IC {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100657 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100658 enum TypeInfo {
659 UNINITIALIZED,
660 SMI,
661 INT32,
662 HEAP_NUMBER,
Steve Block44f0eee2011-05-26 01:26:41 +0100663 ODDBALL,
Ben Murdoch257744e2011-11-30 15:57:28 +0000664 BOTH_STRING, // Only used for addition operation.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100665 STRING, // Only used for addition operation. At least one string operand.
666 GENERIC
667 };
668
Ben Murdoch257744e2011-11-30 15:57:28 +0000669 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100670
671 void patch(Code* code);
672
673 static const char* GetName(TypeInfo type_info);
674
675 static State ToState(TypeInfo type_info);
676
677 static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
678
679 static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
680};
681
682
683class CompareIC: public IC {
684 public:
685 enum State {
686 UNINITIALIZED,
687 SMIS,
688 HEAP_NUMBERS,
Ben Murdoch257744e2011-11-30 15:57:28 +0000689 SYMBOLS,
690 STRINGS,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100691 OBJECTS,
692 GENERIC
693 };
694
Steve Block44f0eee2011-05-26 01:26:41 +0100695 CompareIC(Isolate* isolate, Token::Value op)
696 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100697
698 // Update the inline cache for the given operands.
699 void UpdateCaches(Handle<Object> x, Handle<Object> y);
700
701 // Factory method for getting an uninitialized compare stub.
702 static Handle<Code> GetUninitialized(Token::Value op);
703
704 // Helper function for computing the condition for a compare operation.
705 static Condition ComputeCondition(Token::Value op);
706
707 // Helper function for determining the state of a compare IC.
708 static State ComputeState(Code* target);
709
710 static const char* GetStateName(State state);
711
712 private:
713 State TargetState(State state, bool has_inlined_smi_code,
714 Handle<Object> x, Handle<Object> y);
715
716 bool strict() const { return op_ == Token::EQ_STRICT; }
717 Condition GetCondition() const { return ComputeCondition(op_); }
718 State GetState() { return ComputeState(target()); }
719
720 Token::Value op_;
721};
722
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000723
724class ToBooleanIC: public IC {
725 public:
726 explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
727
728 void patch(Code* code);
729};
730
731
Ben Murdoch257744e2011-11-30 15:57:28 +0000732// Helper for BinaryOpIC and CompareIC.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100733void PatchInlinedSmiCode(Address address);
734
Steve Blocka7e24c12009-10-30 11:49:00 +0000735} } // namespace v8::internal
736
737#endif // V8_IC_H_