blob: 25d0986055aeb7b6051f7a8973f790cc01cee288 [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 Murdochb0fe1622011-05-05 13:52:32 +010062 ICU(CompareIC_Miss)
Steve Blocka7e24c12009-10-30 11:49:00 +000063//
64// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
65// and KeyedStoreIC.
66//
67class IC {
68 public:
69
70 // 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,
152 Code* new_target,
153 const char* extra_info = "");
Steve Blocka7e24c12009-10-30 11:49:00 +0000154#endif
155
Steve Block44f0eee2011-05-26 01:26:41 +0100156 Failure* TypeError(const char* type,
157 Handle<Object> object,
158 Handle<Object> key);
159 Failure* ReferenceError(const char* type, Handle<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000160
161 // Access the target code for the given IC address.
162 static inline Code* GetTargetAtAddress(Address address);
163 static inline void SetTargetAtAddress(Address address, Code* target);
164
165 private:
166 // Frame pointer for the frame that uses (calls) the IC.
167 Address fp_;
168
169 // All access to the program counter of an IC structure is indirect
170 // to make the code GC safe. This feature is crucial since
171 // GetProperty and SetProperty are called and they in turn might
172 // invoke the garbage collector.
173 Address* pc_address_;
174
Steve Block44f0eee2011-05-26 01:26:41 +0100175 Isolate* isolate_;
176
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
178};
179
180
181// An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
182// cannot make forward declarations to an enum.
183class IC_Utility {
184 public:
185 explicit IC_Utility(IC::UtilityId id)
186 : address_(IC::AddressFromUtilityId(id)), id_(id) {}
187
188 Address address() const { return address_; }
189
190 IC::UtilityId id() const { return id_; }
191 private:
192 Address address_;
193 IC::UtilityId id_;
194};
195
196
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100197class CallICBase: public IC {
Ben Murdoch257744e2011-11-30 15:57:28 +0000198 public:
199 class Contextual: public BitField<bool, 0, 1> {};
200 class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
201
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100202 protected:
Steve Block44f0eee2011-05-26 01:26:41 +0100203 CallICBase(Code::Kind kind, Isolate* isolate)
204 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000205
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100206 public:
John Reck59135872010-11-02 12:39:01 -0700207 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100208 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700209 Handle<Object> object,
210 Handle<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000211
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100212 protected:
213 Code::Kind kind_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000214
Ben Murdochb8e0da22011-05-16 14:20:40 +0100215 bool TryUpdateExtraICState(LookupResult* lookup,
216 Handle<Object> object,
217 Code::ExtraICState* extra_ic_state);
218
219 MUST_USE_RESULT MaybeObject* ComputeMonomorphicStub(
220 LookupResult* lookup,
221 State state,
222 Code::ExtraICState extra_ic_state,
223 Handle<Object> object,
224 Handle<String> name);
225
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 // Update the inline cache and the global stub cache based on the
227 // lookup result.
228 void UpdateCaches(LookupResult* lookup,
229 State state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100230 Code::ExtraICState extra_ic_state,
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 Handle<Object> object,
232 Handle<String> name);
233
234 // Returns a JSFunction if the object can be called as a function,
235 // and patches the stack to be ready for the call.
236 // Otherwise, it returns the undefined value.
237 Object* TryCallAsFunction(Object* object);
238
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100239 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
Leon Clarkee46be812010-01-19 14:06:41 +0000240
Steve Blocka7e24c12009-10-30 11:49:00 +0000241 static void Clear(Address address, Code* target);
Ben Murdoch257744e2011-11-30 15:57:28 +0000242
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 friend class IC;
244};
245
246
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100247class CallIC: public CallICBase {
248 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100249 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
250 ASSERT(target()->is_call_stub());
251 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100252
253 // Code generator routines.
Ben Murdoch257744e2011-11-30 15:57:28 +0000254 static void GenerateInitialize(MacroAssembler* masm,
255 int argc,
256 Code::ExtraICState extra_ic_state) {
257 GenerateMiss(masm, argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100258 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000259 static void GenerateMiss(MacroAssembler* masm,
260 int argc,
261 Code::ExtraICState extra_ic_state);
262 static void GenerateMegamorphic(MacroAssembler* masm,
263 int argc,
264 Code::ExtraICState extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100265 static void GenerateNormal(MacroAssembler* masm, int argc);
266};
267
268
269class KeyedCallIC: public CallICBase {
270 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100271 explicit KeyedCallIC(Isolate* isolate)
272 : CallICBase(Code::KEYED_CALL_IC, isolate) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100273 ASSERT(target()->is_keyed_call_stub());
274 }
275
John Reck59135872010-11-02 12:39:01 -0700276 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
277 Handle<Object> object,
278 Handle<Object> key);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100279
280 // Code generator routines.
281 static void GenerateInitialize(MacroAssembler* masm, int argc) {
282 GenerateMiss(masm, argc);
283 }
284 static void GenerateMiss(MacroAssembler* masm, int argc);
285 static void GenerateMegamorphic(MacroAssembler* masm, int argc);
286 static void GenerateNormal(MacroAssembler* masm, int argc);
287};
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
348 static const int kMaxKeyedPolymorphism = 4;
349
350 virtual MaybeObject* GetFastElementStubWithoutMapCheck(
351 bool is_js_array) = 0;
352
353 virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
354 ExternalArrayType array_type) = 0;
355
356 protected:
357 virtual Code* string_stub() {
358 return NULL;
359 }
360
361 virtual Code::Kind kind() const = 0;
362
363 virtual String* GetStubNameForCache(IC::State ic_state) = 0;
364
365 MaybeObject* ComputeStub(JSObject* receiver,
366 bool is_store,
367 StrictModeFlag strict_mode,
368 Code* default_stub);
369
370 virtual MaybeObject* ConstructMegamorphicStub(
371 MapList* receiver_maps,
372 CodeList* targets,
373 StrictModeFlag strict_mode) = 0;
374
375 private:
376 void GetReceiverMapsForStub(Code* stub, MapList* result);
377
378 MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
379 Map* receiver_map,
380 StrictModeFlag strict_mode,
381 Code* generic_stub);
382
383 MaybeObject* ComputeMonomorphicStub(JSObject* receiver,
384 bool is_store,
385 StrictModeFlag strict_mode,
386 Code* default_stub);
387};
388
389
390class KeyedLoadIC: public KeyedIC {
391 public:
392 explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +0100393 ASSERT(target()->is_keyed_load_stub());
394 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000395
John Reck59135872010-11-02 12:39:01 -0700396 MUST_USE_RESULT MaybeObject* Load(State state,
397 Handle<Object> object,
Ben Murdoch257744e2011-11-30 15:57:28 +0000398 Handle<Object> key,
399 bool force_generic_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000400
401 // Code generator routines.
Ben Murdoch257744e2011-11-30 15:57:28 +0000402 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
Andrei Popescu402d9372010-02-26 13:31:12 +0000403 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000404 static void GenerateInitialize(MacroAssembler* masm) {
405 GenerateMiss(masm, false);
406 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000407 static void GeneratePreMonomorphic(MacroAssembler* masm) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000408 GenerateMiss(masm, false);
Andrei Popescu402d9372010-02-26 13:31:12 +0000409 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 static void GenerateGeneric(MacroAssembler* masm);
Leon Clarkee46be812010-01-19 14:06:41 +0000411 static void GenerateString(MacroAssembler* masm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000412
Andrei Popescu402d9372010-02-26 13:31:12 +0000413 static void GenerateIndexedInterceptor(MacroAssembler* masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000414
Leon Clarked91b9f72010-01-27 17:25:45 +0000415 // Bit mask to be tested against bit field for the cases when
416 // generic stub should go into slow case.
417 // Access check is necessary explicitly since generic stub does not perform
418 // map checks.
419 static const int kSlowCaseBitFieldMask =
420 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
421
Ben Murdoch257744e2011-11-30 15:57:28 +0000422 virtual MaybeObject* GetFastElementStubWithoutMapCheck(
423 bool is_js_array);
424
425 virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
426 ExternalArrayType array_type);
427
428 protected:
429 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
430
431 virtual String* GetStubNameForCache(IC::State ic_state);
432
433 virtual MaybeObject* ConstructMegamorphicStub(
434 MapList* receiver_maps,
435 CodeList* targets,
436 StrictModeFlag strict_mode);
437
438 virtual Code* string_stub() {
439 return isolate()->builtins()->builtin(
440 Builtins::kKeyedLoadIC_String);
441 }
442
Steve Block6ded16b2010-05-10 14:33:55 +0100443 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 // Update the inline cache.
445 void UpdateCaches(LookupResult* lookup,
446 State state,
447 Handle<Object> object,
448 Handle<String> name);
449
450 // Stub accessors.
451 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100452 return Isolate::Current()->builtins()->builtin(
453 Builtins::kKeyedLoadIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 }
Steve Block44f0eee2011-05-26 01:26:41 +0100455 Code* megamorphic_stub() {
456 return isolate()->builtins()->builtin(
457 Builtins::kKeyedLoadIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 }
Steve Block44f0eee2011-05-26 01:26:41 +0100459 Code* generic_stub() {
460 return isolate()->builtins()->builtin(
461 Builtins::kKeyedLoadIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 }
Steve Block44f0eee2011-05-26 01:26:41 +0100463 Code* pre_monomorphic_stub() {
464 return isolate()->builtins()->builtin(
465 Builtins::kKeyedLoadIC_PreMonomorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000466 }
Steve Block44f0eee2011-05-26 01:26:41 +0100467 Code* indexed_interceptor_stub() {
468 return isolate()->builtins()->builtin(
469 Builtins::kKeyedLoadIC_IndexedInterceptor);
Andrei Popescu402d9372010-02-26 13:31:12 +0000470 }
471
Steve Blocka7e24c12009-10-30 11:49:00 +0000472 static void Clear(Address address, Code* target);
473
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 friend class IC;
475};
476
477
478class StoreIC: public IC {
479 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100480 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
481 ASSERT(target()->is_store_stub());
482 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000483
John Reck59135872010-11-02 12:39:01 -0700484 MUST_USE_RESULT MaybeObject* Store(State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100485 StrictModeFlag strict_mode,
John Reck59135872010-11-02 12:39:01 -0700486 Handle<Object> object,
487 Handle<String> name,
488 Handle<Object> value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000489
490 // Code generators for stub routines. Only called once at startup.
Leon Clarke4515c472010-02-03 11:58:03 +0000491 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 static void GenerateMiss(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100493 static void GenerateMegamorphic(MacroAssembler* masm,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100494 StrictModeFlag strict_mode);
Steve Block6ded16b2010-05-10 14:33:55 +0100495 static void GenerateArrayLength(MacroAssembler* masm);
Steve Block8defd9f2010-07-08 12:39:36 +0100496 static void GenerateNormal(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100497 static void GenerateGlobalProxy(MacroAssembler* masm,
498 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000499
500 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 // Update the inline cache and the global stub cache based on the
502 // lookup result.
503 void UpdateCaches(LookupResult* lookup,
Steve Block1e0659c2011-05-24 12:43:12 +0100504 State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100505 StrictModeFlag strict_mode,
Steve Block1e0659c2011-05-24 12:43:12 +0100506 Handle<JSObject> receiver,
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 Handle<String> name,
508 Handle<Object> value);
509
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100510 void set_target(Code* code) {
511 // Strict mode must be preserved across IC patching.
512 ASSERT((code->extra_ic_state() & kStrictMode) ==
513 (target()->extra_ic_state() & kStrictMode));
514 IC::set_target(code);
515 }
516
Steve Blocka7e24c12009-10-30 11:49:00 +0000517 // Stub accessors.
Steve Block44f0eee2011-05-26 01:26:41 +0100518 Code* megamorphic_stub() {
519 return isolate()->builtins()->builtin(
520 Builtins::kStoreIC_Megamorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 }
Steve Block44f0eee2011-05-26 01:26:41 +0100522 Code* megamorphic_stub_strict() {
523 return isolate()->builtins()->builtin(
524 Builtins::kStoreIC_Megamorphic_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100525 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100527 return Isolate::Current()->builtins()->builtin(
528 Builtins::kStoreIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 }
Steve Block1e0659c2011-05-24 12:43:12 +0100530 static Code* initialize_stub_strict() {
Steve Block44f0eee2011-05-26 01:26:41 +0100531 return Isolate::Current()->builtins()->builtin(
532 Builtins::kStoreIC_Initialize_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100533 }
Steve Block44f0eee2011-05-26 01:26:41 +0100534 Code* global_proxy_stub() {
535 return isolate()->builtins()->builtin(
536 Builtins::kStoreIC_GlobalProxy);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100537 }
Steve Block44f0eee2011-05-26 01:26:41 +0100538 Code* global_proxy_stub_strict() {
539 return isolate()->builtins()->builtin(
540 Builtins::kStoreIC_GlobalProxy_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100541 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000542
543 static void Clear(Address address, Code* target);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100544
Steve Blocka7e24c12009-10-30 11:49:00 +0000545 friend class IC;
546};
547
548
Ben Murdoch257744e2011-11-30 15:57:28 +0000549class KeyedStoreIC: public KeyedIC {
Steve Blocka7e24c12009-10-30 11:49:00 +0000550 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000551 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
552 ASSERT(target()->is_keyed_store_stub());
553 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000554
John Reck59135872010-11-02 12:39:01 -0700555 MUST_USE_RESULT MaybeObject* Store(State state,
Ben Murdoch257744e2011-11-30 15:57:28 +0000556 StrictModeFlag strict_mode,
John Reck59135872010-11-02 12:39:01 -0700557 Handle<Object> object,
558 Handle<Object> name,
Ben Murdoch257744e2011-11-30 15:57:28 +0000559 Handle<Object> value,
560 bool force_generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000561
562 // Code generators for stub routines. Only called once at startup.
Ben Murdoch257744e2011-11-30 15:57:28 +0000563 static void GenerateInitialize(MacroAssembler* masm) {
564 GenerateMiss(masm, false);
565 }
566 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
567 static void GenerateSlow(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100568 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
569 StrictModeFlag strict_mode);
570 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000571
Ben Murdoch257744e2011-11-30 15:57:28 +0000572 virtual MaybeObject* GetFastElementStubWithoutMapCheck(
573 bool is_js_array);
Steve Block053d10c2011-06-13 19:13:29 +0100574
Ben Murdoch257744e2011-11-30 15:57:28 +0000575 virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
576 ExternalArrayType array_type);
Steve Block053d10c2011-06-13 19:13:29 +0100577
Ben Murdoch257744e2011-11-30 15:57:28 +0000578 protected:
579 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
580
581 virtual String* GetStubNameForCache(IC::State ic_state);
582
583 virtual MaybeObject* ConstructMegamorphicStub(
584 MapList* receiver_maps,
585 CodeList* targets,
586 StrictModeFlag strict_mode);
587
588 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000589 // Update the inline cache.
590 void UpdateCaches(LookupResult* lookup,
591 State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100592 StrictModeFlag strict_mode,
Steve Blocka7e24c12009-10-30 11:49:00 +0000593 Handle<JSObject> receiver,
594 Handle<String> name,
595 Handle<Object> value);
596
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100597 void set_target(Code* code) {
598 // Strict mode must be preserved across IC patching.
599 ASSERT((code->extra_ic_state() & kStrictMode) ==
600 (target()->extra_ic_state() & kStrictMode));
601 IC::set_target(code);
602 }
603
Steve Blocka7e24c12009-10-30 11:49:00 +0000604 // Stub accessors.
605 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100606 return Isolate::Current()->builtins()->builtin(
607 Builtins::kKeyedStoreIC_Initialize);
608 }
609 Code* megamorphic_stub() {
610 return isolate()->builtins()->builtin(
611 Builtins::kKeyedStoreIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000612 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100613 static Code* initialize_stub_strict() {
Steve Block44f0eee2011-05-26 01:26:41 +0100614 return Isolate::Current()->builtins()->builtin(
615 Builtins::kKeyedStoreIC_Initialize_Strict);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100616 }
Steve Block44f0eee2011-05-26 01:26:41 +0100617 Code* megamorphic_stub_strict() {
618 return isolate()->builtins()->builtin(
619 Builtins::kKeyedStoreIC_Generic_Strict);
Steve Blocka7e24c12009-10-30 11:49:00 +0000620 }
Steve Block44f0eee2011-05-26 01:26:41 +0100621 Code* generic_stub() {
622 return isolate()->builtins()->builtin(
623 Builtins::kKeyedStoreIC_Generic);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100624 }
Steve Block44f0eee2011-05-26 01:26:41 +0100625 Code* generic_stub_strict() {
626 return isolate()->builtins()->builtin(
627 Builtins::kKeyedStoreIC_Generic_Strict);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100628 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000629
630 static void Clear(Address address, Code* target);
631
Steve Blocka7e24c12009-10-30 11:49:00 +0000632 friend class IC;
633};
634
635
Ben Murdoch257744e2011-11-30 15:57:28 +0000636class UnaryOpIC: public IC {
637 public:
638
639 // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
640 // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
641 enum TypeInfo {
642 UNINITIALIZED,
643 SMI,
644 HEAP_NUMBER,
645 GENERIC
646 };
647
648 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
649
650 void patch(Code* code);
651
652 static const char* GetName(TypeInfo type_info);
653
654 static State ToState(TypeInfo type_info);
655
656 static TypeInfo GetTypeInfo(Handle<Object> operand);
657
658 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
659};
660
661
Ben Murdochb0fe1622011-05-05 13:52:32 +0100662// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
Ben Murdoch257744e2011-11-30 15:57:28 +0000663class BinaryOpIC: public IC {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 public:
665
666 enum TypeInfo {
667 UNINITIALIZED,
668 SMI,
669 INT32,
670 HEAP_NUMBER,
Steve Block44f0eee2011-05-26 01:26:41 +0100671 ODDBALL,
Ben Murdoch257744e2011-11-30 15:57:28 +0000672 BOTH_STRING, // Only used for addition operation.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100673 STRING, // Only used for addition operation. At least one string operand.
674 GENERIC
675 };
676
Ben Murdoch257744e2011-11-30 15:57:28 +0000677 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678
679 void patch(Code* code);
680
681 static const char* GetName(TypeInfo type_info);
682
683 static State ToState(TypeInfo type_info);
684
685 static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
686
687 static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
688};
689
690
691class CompareIC: public IC {
692 public:
693 enum State {
694 UNINITIALIZED,
695 SMIS,
696 HEAP_NUMBERS,
Ben Murdoch257744e2011-11-30 15:57:28 +0000697 SYMBOLS,
698 STRINGS,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100699 OBJECTS,
700 GENERIC
701 };
702
Steve Block44f0eee2011-05-26 01:26:41 +0100703 CompareIC(Isolate* isolate, Token::Value op)
704 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705
706 // Update the inline cache for the given operands.
707 void UpdateCaches(Handle<Object> x, Handle<Object> y);
708
709 // Factory method for getting an uninitialized compare stub.
710 static Handle<Code> GetUninitialized(Token::Value op);
711
712 // Helper function for computing the condition for a compare operation.
713 static Condition ComputeCondition(Token::Value op);
714
715 // Helper function for determining the state of a compare IC.
716 static State ComputeState(Code* target);
717
718 static const char* GetStateName(State state);
719
720 private:
721 State TargetState(State state, bool has_inlined_smi_code,
722 Handle<Object> x, Handle<Object> y);
723
724 bool strict() const { return op_ == Token::EQ_STRICT; }
725 Condition GetCondition() const { return ComputeCondition(op_); }
726 State GetState() { return ComputeState(target()); }
727
728 Token::Value op_;
729};
730
Ben Murdoch257744e2011-11-30 15:57:28 +0000731// Helper for BinaryOpIC and CompareIC.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100732void PatchInlinedSmiCode(Address address);
733
Steve Blocka7e24c12009-10-30 11:49:00 +0000734} } // namespace v8::internal
735
736#endif // V8_IC_H_