blob: 2236ba37b67f18d37532b3145af9b53956e7d4c8 [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,
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);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000287 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100288};
289
290
Steve Blocka7e24c12009-10-30 11:49:00 +0000291class LoadIC: public IC {
292 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100293 explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
294 ASSERT(target()->is_load_stub());
295 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000296
John Reck59135872010-11-02 12:39:01 -0700297 MUST_USE_RESULT MaybeObject* Load(State state,
298 Handle<Object> object,
299 Handle<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300
301 // Code generator routines.
Andrei Popescu402d9372010-02-26 13:31:12 +0000302 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
303 static void GeneratePreMonomorphic(MacroAssembler* masm) {
304 GenerateMiss(masm);
305 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 static void GenerateMiss(MacroAssembler* masm);
307 static void GenerateMegamorphic(MacroAssembler* masm);
308 static void GenerateNormal(MacroAssembler* masm);
309
310 // Specialized code generator routines.
311 static void GenerateArrayLength(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100312 static void GenerateStringLength(MacroAssembler* masm,
313 bool support_wrappers);
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 static void GenerateFunctionPrototype(MacroAssembler* masm);
315
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000317 // Update the inline cache and the global stub cache based on the
318 // lookup result.
319 void UpdateCaches(LookupResult* lookup,
320 State state,
321 Handle<Object> object,
322 Handle<String> name);
323
324 // Stub accessors.
Steve Block44f0eee2011-05-26 01:26:41 +0100325 Code* megamorphic_stub() {
326 return isolate()->builtins()->builtin(
327 Builtins::kLoadIC_Megamorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 }
329 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100330 return Isolate::Current()->builtins()->builtin(
331 Builtins::kLoadIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 }
Steve Block44f0eee2011-05-26 01:26:41 +0100333 Code* pre_monomorphic_stub() {
334 return isolate()->builtins()->builtin(
335 Builtins::kLoadIC_PreMonomorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000336 }
337
338 static void Clear(Address address, Code* target);
339
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 friend class IC;
341};
342
343
Ben Murdoch257744e2011-11-30 15:57:28 +0000344class KeyedIC: public IC {
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000346 explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
347 virtual ~KeyedIC() {}
348
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000349 virtual MaybeObject* GetElementStubWithoutMapCheck(
350 bool is_js_array,
351 JSObject::ElementsKind elements_kind) = 0;
Ben Murdoch257744e2011-11-30 15:57:28 +0000352
353 protected:
354 virtual Code* string_stub() {
355 return NULL;
356 }
357
358 virtual Code::Kind kind() const = 0;
359
Ben Murdoch257744e2011-11-30 15:57:28 +0000360 MaybeObject* ComputeStub(JSObject* receiver,
361 bool is_store,
362 StrictModeFlag strict_mode,
363 Code* default_stub);
364
365 virtual MaybeObject* ConstructMegamorphicStub(
366 MapList* receiver_maps,
367 CodeList* targets,
368 StrictModeFlag strict_mode) = 0;
369
370 private:
371 void GetReceiverMapsForStub(Code* stub, MapList* result);
372
373 MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
374 Map* receiver_map,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000375 StrictModeFlag strict_mode);
Ben Murdoch257744e2011-11-30 15:57:28 +0000376
377 MaybeObject* ComputeMonomorphicStub(JSObject* receiver,
378 bool is_store,
379 StrictModeFlag strict_mode,
380 Code* default_stub);
381};
382
383
384class KeyedLoadIC: public KeyedIC {
385 public:
386 explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +0100387 ASSERT(target()->is_keyed_load_stub());
388 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000389
John Reck59135872010-11-02 12:39:01 -0700390 MUST_USE_RESULT MaybeObject* Load(State state,
391 Handle<Object> object,
Ben Murdoch257744e2011-11-30 15:57:28 +0000392 Handle<Object> key,
393 bool force_generic_stub);
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
395 // Code generator routines.
Ben Murdoch257744e2011-11-30 15:57:28 +0000396 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
Andrei Popescu402d9372010-02-26 13:31:12 +0000397 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000398 static void GenerateInitialize(MacroAssembler* masm) {
399 GenerateMiss(masm, false);
400 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000401 static void GeneratePreMonomorphic(MacroAssembler* masm) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000402 GenerateMiss(masm, false);
Andrei Popescu402d9372010-02-26 13:31:12 +0000403 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 static void GenerateGeneric(MacroAssembler* masm);
Leon Clarkee46be812010-01-19 14:06:41 +0000405 static void GenerateString(MacroAssembler* masm);
Andrei Popescu402d9372010-02-26 13:31:12 +0000406 static void GenerateIndexedInterceptor(MacroAssembler* masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000407 static void GenerateNonStrictArguments(MacroAssembler* masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000408
Leon Clarked91b9f72010-01-27 17:25:45 +0000409 // Bit mask to be tested against bit field for the cases when
410 // generic stub should go into slow case.
411 // Access check is necessary explicitly since generic stub does not perform
412 // map checks.
413 static const int kSlowCaseBitFieldMask =
414 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
415
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000416 virtual MaybeObject* GetElementStubWithoutMapCheck(
417 bool is_js_array,
418 JSObject::ElementsKind elements_kind);
Ben Murdoch257744e2011-11-30 15:57:28 +0000419
420 protected:
421 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
422
Ben Murdoch257744e2011-11-30 15:57:28 +0000423 virtual MaybeObject* ConstructMegamorphicStub(
424 MapList* receiver_maps,
425 CodeList* targets,
426 StrictModeFlag strict_mode);
427
428 virtual Code* string_stub() {
429 return isolate()->builtins()->builtin(
430 Builtins::kKeyedLoadIC_String);
431 }
432
Steve Block6ded16b2010-05-10 14:33:55 +0100433 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 // Update the inline cache.
435 void UpdateCaches(LookupResult* lookup,
436 State state,
437 Handle<Object> object,
438 Handle<String> name);
439
440 // Stub accessors.
441 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100442 return Isolate::Current()->builtins()->builtin(
443 Builtins::kKeyedLoadIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 }
Steve Block44f0eee2011-05-26 01:26:41 +0100445 Code* megamorphic_stub() {
446 return isolate()->builtins()->builtin(
447 Builtins::kKeyedLoadIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 }
Steve Block44f0eee2011-05-26 01:26:41 +0100449 Code* generic_stub() {
450 return isolate()->builtins()->builtin(
451 Builtins::kKeyedLoadIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 }
Steve Block44f0eee2011-05-26 01:26:41 +0100453 Code* pre_monomorphic_stub() {
454 return isolate()->builtins()->builtin(
455 Builtins::kKeyedLoadIC_PreMonomorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000456 }
Steve Block44f0eee2011-05-26 01:26:41 +0100457 Code* indexed_interceptor_stub() {
458 return isolate()->builtins()->builtin(
459 Builtins::kKeyedLoadIC_IndexedInterceptor);
Andrei Popescu402d9372010-02-26 13:31:12 +0000460 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000461 Code* non_strict_arguments_stub() {
462 return isolate()->builtins()->builtin(
463 Builtins::kKeyedLoadIC_NonStrictArguments);
464 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000465
Steve Blocka7e24c12009-10-30 11:49:00 +0000466 static void Clear(Address address, Code* target);
467
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 friend class IC;
469};
470
471
472class StoreIC: public IC {
473 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100474 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
475 ASSERT(target()->is_store_stub());
476 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000477
John Reck59135872010-11-02 12:39:01 -0700478 MUST_USE_RESULT MaybeObject* Store(State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100479 StrictModeFlag strict_mode,
John Reck59135872010-11-02 12:39:01 -0700480 Handle<Object> object,
481 Handle<String> name,
482 Handle<Object> value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000483
484 // Code generators for stub routines. Only called once at startup.
Leon Clarke4515c472010-02-03 11:58:03 +0000485 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 static void GenerateMiss(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100487 static void GenerateMegamorphic(MacroAssembler* masm,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100488 StrictModeFlag strict_mode);
Steve Block6ded16b2010-05-10 14:33:55 +0100489 static void GenerateArrayLength(MacroAssembler* masm);
Steve Block8defd9f2010-07-08 12:39:36 +0100490 static void GenerateNormal(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100491 static void GenerateGlobalProxy(MacroAssembler* masm,
492 StrictModeFlag strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000493
494 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000495 // Update the inline cache and the global stub cache based on the
496 // lookup result.
497 void UpdateCaches(LookupResult* lookup,
Steve Block1e0659c2011-05-24 12:43:12 +0100498 State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100499 StrictModeFlag strict_mode,
Steve Block1e0659c2011-05-24 12:43:12 +0100500 Handle<JSObject> receiver,
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 Handle<String> name,
502 Handle<Object> value);
503
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100504 void set_target(Code* code) {
505 // Strict mode must be preserved across IC patching.
506 ASSERT((code->extra_ic_state() & kStrictMode) ==
507 (target()->extra_ic_state() & kStrictMode));
508 IC::set_target(code);
509 }
510
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 // Stub accessors.
Steve Block44f0eee2011-05-26 01:26:41 +0100512 Code* megamorphic_stub() {
513 return isolate()->builtins()->builtin(
514 Builtins::kStoreIC_Megamorphic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000515 }
Steve Block44f0eee2011-05-26 01:26:41 +0100516 Code* megamorphic_stub_strict() {
517 return isolate()->builtins()->builtin(
518 Builtins::kStoreIC_Megamorphic_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100519 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000520 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100521 return Isolate::Current()->builtins()->builtin(
522 Builtins::kStoreIC_Initialize);
Steve Blocka7e24c12009-10-30 11:49:00 +0000523 }
Steve Block1e0659c2011-05-24 12:43:12 +0100524 static Code* initialize_stub_strict() {
Steve Block44f0eee2011-05-26 01:26:41 +0100525 return Isolate::Current()->builtins()->builtin(
526 Builtins::kStoreIC_Initialize_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100527 }
Steve Block44f0eee2011-05-26 01:26:41 +0100528 Code* global_proxy_stub() {
529 return isolate()->builtins()->builtin(
530 Builtins::kStoreIC_GlobalProxy);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100531 }
Steve Block44f0eee2011-05-26 01:26:41 +0100532 Code* global_proxy_stub_strict() {
533 return isolate()->builtins()->builtin(
534 Builtins::kStoreIC_GlobalProxy_Strict);
Steve Block1e0659c2011-05-24 12:43:12 +0100535 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000536
537 static void Clear(Address address, Code* target);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100538
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 friend class IC;
540};
541
542
Ben Murdoch257744e2011-11-30 15:57:28 +0000543class KeyedStoreIC: public KeyedIC {
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000545 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
546 ASSERT(target()->is_keyed_store_stub());
547 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000548
John Reck59135872010-11-02 12:39:01 -0700549 MUST_USE_RESULT MaybeObject* Store(State state,
Ben Murdoch257744e2011-11-30 15:57:28 +0000550 StrictModeFlag strict_mode,
John Reck59135872010-11-02 12:39:01 -0700551 Handle<Object> object,
552 Handle<Object> name,
Ben Murdoch257744e2011-11-30 15:57:28 +0000553 Handle<Object> value,
554 bool force_generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000555
556 // Code generators for stub routines. Only called once at startup.
Ben Murdoch257744e2011-11-30 15:57:28 +0000557 static void GenerateInitialize(MacroAssembler* masm) {
558 GenerateMiss(masm, false);
559 }
560 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
561 static void GenerateSlow(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100562 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
563 StrictModeFlag strict_mode);
564 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000565 static void GenerateNonStrictArguments(MacroAssembler* masm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000566
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000567 virtual MaybeObject* GetElementStubWithoutMapCheck(
568 bool is_js_array,
569 JSObject::ElementsKind elements_kind);
Steve Block053d10c2011-06-13 19:13:29 +0100570
Ben Murdoch257744e2011-11-30 15:57:28 +0000571 protected:
572 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
573
Ben Murdoch257744e2011-11-30 15:57:28 +0000574 virtual MaybeObject* ConstructMegamorphicStub(
575 MapList* receiver_maps,
576 CodeList* targets,
577 StrictModeFlag strict_mode);
578
579 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 // Update the inline cache.
581 void UpdateCaches(LookupResult* lookup,
582 State state,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100583 StrictModeFlag strict_mode,
Steve Blocka7e24c12009-10-30 11:49:00 +0000584 Handle<JSObject> receiver,
585 Handle<String> name,
586 Handle<Object> value);
587
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100588 void set_target(Code* code) {
589 // Strict mode must be preserved across IC patching.
590 ASSERT((code->extra_ic_state() & kStrictMode) ==
591 (target()->extra_ic_state() & kStrictMode));
592 IC::set_target(code);
593 }
594
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 // Stub accessors.
596 static Code* initialize_stub() {
Steve Block44f0eee2011-05-26 01:26:41 +0100597 return Isolate::Current()->builtins()->builtin(
598 Builtins::kKeyedStoreIC_Initialize);
599 }
600 Code* megamorphic_stub() {
601 return isolate()->builtins()->builtin(
602 Builtins::kKeyedStoreIC_Generic);
Steve Blocka7e24c12009-10-30 11:49:00 +0000603 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100604 static Code* initialize_stub_strict() {
Steve Block44f0eee2011-05-26 01:26:41 +0100605 return Isolate::Current()->builtins()->builtin(
606 Builtins::kKeyedStoreIC_Initialize_Strict);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100607 }
Steve Block44f0eee2011-05-26 01:26:41 +0100608 Code* megamorphic_stub_strict() {
609 return isolate()->builtins()->builtin(
610 Builtins::kKeyedStoreIC_Generic_Strict);
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 }
Steve Block44f0eee2011-05-26 01:26:41 +0100612 Code* generic_stub() {
613 return isolate()->builtins()->builtin(
614 Builtins::kKeyedStoreIC_Generic);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100615 }
Steve Block44f0eee2011-05-26 01:26:41 +0100616 Code* generic_stub_strict() {
617 return isolate()->builtins()->builtin(
618 Builtins::kKeyedStoreIC_Generic_Strict);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100619 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000620 Code* non_strict_arguments_stub() {
621 return isolate()->builtins()->builtin(
622 Builtins::kKeyedStoreIC_NonStrictArguments);
623 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
625 static void Clear(Address address, Code* target);
626
Steve Blocka7e24c12009-10-30 11:49:00 +0000627 friend class IC;
628};
629
630
Ben Murdoch257744e2011-11-30 15:57:28 +0000631class UnaryOpIC: public IC {
632 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000633 // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
634 // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
635 enum TypeInfo {
636 UNINITIALIZED,
637 SMI,
638 HEAP_NUMBER,
639 GENERIC
640 };
641
642 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
643
644 void patch(Code* code);
645
646 static const char* GetName(TypeInfo type_info);
647
648 static State ToState(TypeInfo type_info);
649
650 static TypeInfo GetTypeInfo(Handle<Object> operand);
651
652 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
653};
654
655
Ben Murdochb0fe1622011-05-05 13:52:32 +0100656// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
Ben Murdoch257744e2011-11-30 15:57:28 +0000657class BinaryOpIC: public IC {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100658 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100659 enum TypeInfo {
660 UNINITIALIZED,
661 SMI,
662 INT32,
663 HEAP_NUMBER,
Steve Block44f0eee2011-05-26 01:26:41 +0100664 ODDBALL,
Ben Murdoch257744e2011-11-30 15:57:28 +0000665 BOTH_STRING, // Only used for addition operation.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100666 STRING, // Only used for addition operation. At least one string operand.
667 GENERIC
668 };
669
Ben Murdoch257744e2011-11-30 15:57:28 +0000670 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100671
672 void patch(Code* code);
673
674 static const char* GetName(TypeInfo type_info);
675
676 static State ToState(TypeInfo type_info);
677
678 static TypeInfo GetTypeInfo(Handle<Object> left, Handle<Object> right);
679
680 static TypeInfo JoinTypes(TypeInfo x, TypeInfo y);
681};
682
683
684class CompareIC: public IC {
685 public:
686 enum State {
687 UNINITIALIZED,
688 SMIS,
689 HEAP_NUMBERS,
Ben Murdoch257744e2011-11-30 15:57:28 +0000690 SYMBOLS,
691 STRINGS,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100692 OBJECTS,
693 GENERIC
694 };
695
Steve Block44f0eee2011-05-26 01:26:41 +0100696 CompareIC(Isolate* isolate, Token::Value op)
697 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100698
699 // Update the inline cache for the given operands.
700 void UpdateCaches(Handle<Object> x, Handle<Object> y);
701
702 // Factory method for getting an uninitialized compare stub.
703 static Handle<Code> GetUninitialized(Token::Value op);
704
705 // Helper function for computing the condition for a compare operation.
706 static Condition ComputeCondition(Token::Value op);
707
708 // Helper function for determining the state of a compare IC.
709 static State ComputeState(Code* target);
710
711 static const char* GetStateName(State state);
712
713 private:
714 State TargetState(State state, bool has_inlined_smi_code,
715 Handle<Object> x, Handle<Object> y);
716
717 bool strict() const { return op_ == Token::EQ_STRICT; }
718 Condition GetCondition() const { return ComputeCondition(op_); }
719 State GetState() { return ComputeState(target()); }
720
721 Token::Value op_;
722};
723
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000724
725class ToBooleanIC: public IC {
726 public:
727 explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
728
729 void patch(Code* code);
730};
731
732
Ben Murdoch257744e2011-11-30 15:57:28 +0000733// Helper for BinaryOpIC and CompareIC.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100734void PatchInlinedSmiCode(Address address);
735
Steve Blocka7e24c12009-10-30 11:49:00 +0000736} } // namespace v8::internal
737
738#endif // V8_IC_H_