blob: 2236ba37b67f18d37532b3145af9b53956e7d4c8 [file] [log] [blame]
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000031#include "macro-assembler.h"
danno@chromium.org40cb8782011-05-25 07:58:50 +000032#include "type-info.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033
kasperl@chromium.org71affb52009-05-26 05:44:31 +000034namespace v8 {
35namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000037
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000040#define IC_UTIL_LIST(ICU) \
41 ICU(LoadIC_Miss) \
42 ICU(KeyedLoadIC_Miss) \
ager@chromium.orgea91cc52011-05-23 06:06:11 +000043 ICU(KeyedLoadIC_MissForceGeneric) \
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000044 ICU(CallIC_Miss) \
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000045 ICU(KeyedCallIC_Miss) \
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000046 ICU(StoreIC_Miss) \
ager@chromium.org5c838252010-02-19 08:53:10 +000047 ICU(StoreIC_ArrayLength) \
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000048 ICU(SharedStoreIC_ExtendStorage) \
49 ICU(KeyedStoreIC_Miss) \
ager@chromium.orgea91cc52011-05-23 06:06:11 +000050 ICU(KeyedStoreIC_MissForceGeneric) \
51 ICU(KeyedStoreIC_Slow) \
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000052 /* Utilities for IC stubs. */ \
53 ICU(LoadCallbackProperty) \
54 ICU(StoreCallbackProperty) \
55 ICU(LoadPropertyWithInterceptorOnly) \
56 ICU(LoadPropertyWithInterceptorForLoad) \
57 ICU(LoadPropertyWithInterceptorForCall) \
ager@chromium.org5c838252010-02-19 08:53:10 +000058 ICU(KeyedLoadPropertyWithInterceptor) \
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000059 ICU(StoreInterceptorProperty) \
danno@chromium.org40cb8782011-05-25 07:58:50 +000060 ICU(UnaryOp_Patch) \
61 ICU(BinaryOp_Patch) \
ricow@chromium.org9fa09672011-07-25 11:05:35 +000062 ICU(CompareIC_Miss) \
63 ICU(ToBoolean_Patch)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000064//
kasperl@chromium.orge959c182009-07-27 08:59:04 +000065// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
66// and KeyedStoreIC.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067//
68class IC {
69 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000093 IC(FrameDepth depth, Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094
95 // Get the call-site target; used for determining the state.
96 Code* target() { return GetTargetAtAddress(address()); }
97 inline Address address();
98
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000099 // Compute the current IC state based on the target stub, receiver and name.
100 static State StateFrom(Code* target, Object* receiver, Object* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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.
ager@chromium.org236ad962008-09-25 09:45:57 +0000108 RelocInfo::Mode ComputeMode();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109
110 // Returns if this IC is for contextual (no explicit receiver)
111 // access to properties.
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +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() {
ager@chromium.org236ad962008-09-25 09:45:57 +0000122 return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
123 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000125 // 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);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000131 static inline JSObject* GetCodeCacheHolder(Object* object,
132 InlineCacheHolderFlag holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000133
134 protected:
135 Address fp() const { return fp_; }
136 Address pc() const { return *pc_address_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000137 Isolate* isolate() const { return isolate_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000139#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140 // Computes the address in the original code when the code running is
141 // containing break points (calls to DebugBreakXXX builtins).
142 Address OriginalCodeAddress();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000143#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000144
145 // Set the call-site target.
146 void set_target(Code* code) { SetTargetAtAddress(address(), code); }
147
148#ifdef DEBUG
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000149 void TraceIC(const char* type,
150 Handle<Object> name,
151 State old_state,
152 Code* new_target,
153 const char* extra_info = "");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000154#endif
155
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000156 Failure* TypeError(const char* type,
157 Handle<Object> object,
158 Handle<Object> key);
159 Failure* ReferenceError(const char* type, Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166 // 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_;
mads.s.ager31e71382008-08-13 09:32:07 +0000174
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000175 Isolate* isolate_;
176
mads.s.ager31e71382008-08-13 09:32:07 +0000177 DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178};
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
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000197class CallICBase: public IC {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000198 public:
199 class Contextual: public BitField<bool, 0, 1> {};
200 class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
201
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000202 protected:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000203 CallICBase(Code::Kind kind, Isolate* isolate)
204 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000206 public:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000207 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000208 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000209 Handle<Object> object,
210 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000211
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000212 protected:
213 Code::Kind kind_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000215 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226 // Update the inline cache and the global stub cache based on the
227 // lookup result.
228 void UpdateCaches(LookupResult* lookup,
229 State state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000230 Code::ExtraICState extra_ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231 Handle<Object> object,
232 Handle<String> name);
233
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000234 // 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
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000239 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000240
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241 static void Clear(Address address, Code* target);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000242
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243 friend class IC;
244};
245
246
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000247class CallIC: public CallICBase {
248 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000249 explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
250 ASSERT(target()->is_call_stub());
251 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000252
253 // Code generator routines.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000254 static void GenerateInitialize(MacroAssembler* masm,
255 int argc,
256 Code::ExtraICState extra_ic_state) {
257 GenerateMiss(masm, argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000258 }
danno@chromium.org40cb8782011-05-25 07:58:50 +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);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000265 static void GenerateNormal(MacroAssembler* masm, int argc);
266};
267
268
269class KeyedCallIC: public CallICBase {
270 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000271 explicit KeyedCallIC(Isolate* isolate)
272 : CallICBase(Code::KEYED_CALL_IC, isolate) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000273 ASSERT(target()->is_keyed_call_stub());
274 }
275
lrn@chromium.org303ada72010-10-27 09:33:13 +0000276 MUST_USE_RESULT MaybeObject* LoadFunction(State state,
277 Handle<Object> object,
278 Handle<Object> key);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000279
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);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000287 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000288};
289
290
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291class LoadIC: public IC {
292 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000293 explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
294 ASSERT(target()->is_load_stub());
295 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296
lrn@chromium.org303ada72010-10-27 09:33:13 +0000297 MUST_USE_RESULT MaybeObject* Load(State state,
298 Handle<Object> object,
299 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000300
301 // Code generator routines.
ager@chromium.org5c838252010-02-19 08:53:10 +0000302 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
303 static void GeneratePreMonomorphic(MacroAssembler* masm) {
304 GenerateMiss(masm);
305 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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);
ager@chromium.org378b34e2011-01-28 08:04:38 +0000312 static void GenerateStringLength(MacroAssembler* masm,
313 bool support_wrappers);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000314 static void GenerateFunctionPrototype(MacroAssembler* masm);
315
316 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000325 Code* megamorphic_stub() {
326 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000327 Builtins::kLoadIC_Megamorphic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 }
329 static Code* initialize_stub() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000330 return Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000331 Builtins::kLoadIC_Initialize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000333 Code* pre_monomorphic_stub() {
334 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000335 Builtins::kLoadIC_PreMonomorphic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000336 }
337
338 static void Clear(Address address, Code* target);
ager@chromium.org5ec48922009-05-05 07:25:34 +0000339
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000340 friend class IC;
341};
342
343
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000344class KeyedIC: public IC {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000345 public:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000346 explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
347 virtual ~KeyedIC() {}
348
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000349 virtual MaybeObject* GetElementStubWithoutMapCheck(
350 bool is_js_array,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000351 JSObject::ElementsKind elements_kind) = 0;
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000352
353 protected:
354 virtual Code* string_stub() {
355 return NULL;
356 }
357
358 virtual Code::Kind kind() const = 0;
359
ager@chromium.orgea91cc52011-05-23 06:06:11 +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,
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000375 StrictModeFlag strict_mode);
ager@chromium.orgea91cc52011-05-23 06:06:11 +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) {
387 ASSERT(target()->is_keyed_load_stub());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000388 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000389
lrn@chromium.org303ada72010-10-27 09:33:13 +0000390 MUST_USE_RESULT MaybeObject* Load(State state,
391 Handle<Object> object,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000392 Handle<Object> key,
393 bool force_generic_stub);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394
395 // Code generator routines.
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000396 static void GenerateMiss(MacroAssembler* masm, bool force_generic);
ager@chromium.org5c838252010-02-19 08:53:10 +0000397 static void GenerateRuntimeGetProperty(MacroAssembler* masm);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000398 static void GenerateInitialize(MacroAssembler* masm) {
399 GenerateMiss(masm, false);
400 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000401 static void GeneratePreMonomorphic(MacroAssembler* masm) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000402 GenerateMiss(masm, false);
ager@chromium.org5c838252010-02-19 08:53:10 +0000403 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404 static void GenerateGeneric(MacroAssembler* masm);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000405 static void GenerateString(MacroAssembler* masm);
ager@chromium.org5c838252010-02-19 08:53:10 +0000406 static void GenerateIndexedInterceptor(MacroAssembler* masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000407 static void GenerateNonStrictArguments(MacroAssembler* masm);
ager@chromium.org3811b432009-10-28 14:53:37 +0000408
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +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
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000416 virtual MaybeObject* GetElementStubWithoutMapCheck(
417 bool is_js_array,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000418 JSObject::ElementsKind elements_kind);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000419
420 protected:
421 virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
422
ager@chromium.orgea91cc52011-05-23 06:06:11 +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
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000433 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000442 return Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000443 Builtins::kKeyedLoadIC_Initialize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000445 Code* megamorphic_stub() {
446 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000447 Builtins::kKeyedLoadIC_Generic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000448 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000449 Code* generic_stub() {
450 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000451 Builtins::kKeyedLoadIC_Generic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000452 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000453 Code* pre_monomorphic_stub() {
454 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000455 Builtins::kKeyedLoadIC_PreMonomorphic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000457 Code* indexed_interceptor_stub() {
458 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000459 Builtins::kKeyedLoadIC_IndexedInterceptor);
ager@chromium.org5c838252010-02-19 08:53:10 +0000460 }
whesse@chromium.org7b260152011-06-20 15:33:18 +0000461 Code* non_strict_arguments_stub() {
462 return isolate()->builtins()->builtin(
463 Builtins::kKeyedLoadIC_NonStrictArguments);
464 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000465
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466 static void Clear(Address address, Code* target);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000467
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468 friend class IC;
469};
470
471
472class StoreIC: public IC {
473 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000474 explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
475 ASSERT(target()->is_store_stub());
476 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477
lrn@chromium.org303ada72010-10-27 09:33:13 +0000478 MUST_USE_RESULT MaybeObject* Store(State state,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000479 StrictModeFlag strict_mode,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000480 Handle<Object> object,
481 Handle<String> name,
482 Handle<Object> value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000483
484 // Code generators for stub routines. Only called once at startup.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000485 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000486 static void GenerateMiss(MacroAssembler* masm);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000487 static void GenerateMegamorphic(MacroAssembler* masm,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000488 StrictModeFlag strict_mode);
ager@chromium.org5c838252010-02-19 08:53:10 +0000489 static void GenerateArrayLength(MacroAssembler* masm);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000490 static void GenerateNormal(MacroAssembler* masm);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000491 static void GenerateGlobalProxy(MacroAssembler* masm,
492 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493
494 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000495 // Update the inline cache and the global stub cache based on the
496 // lookup result.
497 void UpdateCaches(LookupResult* lookup,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000498 State state,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000499 StrictModeFlag strict_mode,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000500 Handle<JSObject> receiver,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 Handle<String> name,
502 Handle<Object> value);
503
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000504 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511 // Stub accessors.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000512 Code* megamorphic_stub() {
513 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000514 Builtins::kStoreIC_Megamorphic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000515 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000516 Code* megamorphic_stub_strict() {
517 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000518 Builtins::kStoreIC_Megamorphic_Strict);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000519 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000520 static Code* initialize_stub() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000521 return Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000522 Builtins::kStoreIC_Initialize);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000523 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000524 static Code* initialize_stub_strict() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000525 return Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000526 Builtins::kStoreIC_Initialize_Strict);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000527 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000528 Code* global_proxy_stub() {
529 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000530 Builtins::kStoreIC_GlobalProxy);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000531 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000532 Code* global_proxy_stub_strict() {
533 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000534 Builtins::kStoreIC_GlobalProxy_Strict);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000535 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000536
537 static void Clear(Address address, Code* target);
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000538
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539 friend class IC;
540};
541
542
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000543class KeyedStoreIC: public KeyedIC {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544 public:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000545 explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
546 ASSERT(target()->is_keyed_store_stub());
547 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000548
lrn@chromium.org303ada72010-10-27 09:33:13 +0000549 MUST_USE_RESULT MaybeObject* Store(State state,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000550 StrictModeFlag strict_mode,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000551 Handle<Object> object,
552 Handle<Object> name,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000553 Handle<Object> value,
554 bool force_generic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000555
556 // Code generators for stub routines. Only called once at startup.
ager@chromium.orgea91cc52011-05-23 06:06:11 +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);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000562 static void GenerateRuntimeSetProperty(MacroAssembler* masm,
563 StrictModeFlag strict_mode);
564 static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000565 static void GenerateNonStrictArguments(MacroAssembler* masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000567 virtual MaybeObject* GetElementStubWithoutMapCheck(
568 bool is_js_array,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000569 JSObject::ElementsKind elements_kind);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000570
571 protected:
572 virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
573
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000574 virtual MaybeObject* ConstructMegamorphicStub(
575 MapList* receiver_maps,
576 CodeList* targets,
577 StrictModeFlag strict_mode);
578
579 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 // Update the inline cache.
581 void UpdateCaches(LookupResult* lookup,
582 State state,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000583 StrictModeFlag strict_mode,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584 Handle<JSObject> receiver,
585 Handle<String> name,
586 Handle<Object> value);
587
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000588 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595 // Stub accessors.
596 static Code* initialize_stub() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000597 return Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000598 Builtins::kKeyedStoreIC_Initialize);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000599 }
600 Code* megamorphic_stub() {
601 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000602 Builtins::kKeyedStoreIC_Generic);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603 }
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000604 static Code* initialize_stub_strict() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000605 return Isolate::Current()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000606 Builtins::kKeyedStoreIC_Initialize_Strict);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000607 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000608 Code* megamorphic_stub_strict() {
609 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000610 Builtins::kKeyedStoreIC_Generic_Strict);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000612 Code* generic_stub() {
613 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000614 Builtins::kKeyedStoreIC_Generic);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000615 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000616 Code* generic_stub_strict() {
617 return isolate()->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000618 Builtins::kKeyedStoreIC_Generic_Strict);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000619 }
whesse@chromium.org7b260152011-06-20 15:33:18 +0000620 Code* non_strict_arguments_stub() {
621 return isolate()->builtins()->builtin(
622 Builtins::kKeyedStoreIC_NonStrictArguments);
623 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000624
625 static void Clear(Address address, Code* target);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000626
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627 friend class IC;
628};
629
630
danno@chromium.org40cb8782011-05-25 07:58:50 +0000631class UnaryOpIC: public IC {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000632 public:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +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
danno@chromium.org40cb8782011-05-25 07:58:50 +0000642 explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000643
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
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000652 static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000653};
654
655
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000656// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000657class BinaryOpIC: public IC {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000658 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000659 enum TypeInfo {
660 UNINITIALIZED,
661 SMI,
662 INT32,
663 HEAP_NUMBER,
lrn@chromium.org7516f052011-03-30 08:52:27 +0000664 ODDBALL,
danno@chromium.org160a7b02011-04-18 15:51:38 +0000665 BOTH_STRING, // Only used for addition operation.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000666 STRING, // Only used for addition operation. At least one string operand.
667 GENERIC
668 };
669
danno@chromium.org40cb8782011-05-25 07:58:50 +0000670 explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000671
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,
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000690 SYMBOLS,
lrn@chromium.org1c092762011-05-09 09:42:16 +0000691 STRINGS,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000692 OBJECTS,
693 GENERIC
694 };
695
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000696 CompareIC(Isolate* isolate, Token::Value op)
697 : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000698
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:
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000714 State TargetState(State state, bool has_inlined_smi_code,
715 Handle<Object> x, Handle<Object> y);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000716
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
ricow@chromium.org9fa09672011-07-25 11:05:35 +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
danno@chromium.org40cb8782011-05-25 07:58:50 +0000733// Helper for BinaryOpIC and CompareIC.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000734void PatchInlinedSmiCode(Address address);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000735
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000736} } // namespace v8::internal
737
738#endif // V8_IC_H_