Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / v8 / src / ic.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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
31 #include "macro-assembler.h"
32
33 namespace v8 {
34 namespace internal {
35
36
37 const int kMaxKeyedPolymorphism = 4;
38
39
40 // IC_UTIL_LIST defines all utility functions called from generated
41 // inline caching code. The argument for the macro, ICU, is the function name.
42 #define IC_UTIL_LIST(ICU)                             \
43   ICU(LoadIC_Miss)                                    \
44   ICU(KeyedLoadIC_Miss)                               \
45   ICU(CallIC_Miss)                                    \
46   ICU(KeyedCallIC_Miss)                               \
47   ICU(StoreIC_Miss)                                   \
48   ICU(StoreIC_ArrayLength)                            \
49   ICU(StoreIC_Slow)                                   \
50   ICU(SharedStoreIC_ExtendStorage)                    \
51   ICU(KeyedStoreIC_Miss)                              \
52   ICU(KeyedStoreIC_Slow)                              \
53   /* Utilities for IC stubs. */                       \
54   ICU(StoreCallbackProperty)                          \
55   ICU(LoadPropertyWithInterceptorOnly)                \
56   ICU(LoadPropertyWithInterceptorForLoad)             \
57   ICU(LoadPropertyWithInterceptorForCall)             \
58   ICU(KeyedLoadPropertyWithInterceptor)               \
59   ICU(StoreInterceptorProperty)                       \
60   ICU(CompareIC_Miss)                                 \
61   ICU(BinaryOpIC_Miss)                                \
62   ICU(CompareNilIC_Miss)                              \
63   ICU(Unreachable)                                    \
64   ICU(ToBooleanIC_Miss)
65 //
66 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
67 // and KeyedStoreIC.
68 //
69 class IC {
70  public:
71   // The ids for utility called from the generated code.
72   enum UtilityId {
73   #define CONST_NAME(name) k##name,
74     IC_UTIL_LIST(CONST_NAME)
75   #undef CONST_NAME
76     kUtilityCount
77   };
78
79   // Looks up the address of the named utility.
80   static Address AddressFromUtilityId(UtilityId id);
81
82   // Alias the inline cache state type to make the IC code more readable.
83   typedef InlineCacheState State;
84
85   // The IC code is either invoked with no extra frames on the stack
86   // or with a single extra frame for supporting calls.
87   enum FrameDepth {
88     NO_EXTRA_FRAME = 0,
89     EXTRA_CALL_FRAME = 1
90   };
91
92   // Construct the IC structure with the given number of extra
93   // JavaScript frames on the stack.
94   IC(FrameDepth depth, Isolate* isolate);
95   virtual ~IC() {}
96
97   State state() const { return state_; }
98   inline Address address() const;
99
100   // Compute the current IC state based on the target stub, receiver and name.
101   void UpdateState(Handle<Object> receiver, Handle<Object> name);
102   void MarkMonomorphicPrototypeFailure() {
103     state_ = MONOMORPHIC_PROTOTYPE_FAILURE;
104   }
105
106   // Clear the inline cache to initial state.
107   static void Clear(Isolate* isolate, Address address);
108
109 #ifdef DEBUG
110   bool IsLoadStub() const {
111     return target()->is_load_stub() || target()->is_keyed_load_stub();
112   }
113
114   bool IsStoreStub() const {
115     return target()->is_store_stub() || target()->is_keyed_store_stub();
116   }
117
118   bool IsCallStub() const {
119     return target()->is_call_stub() || target()->is_keyed_call_stub();
120   }
121 #endif
122
123   // Determines which map must be used for keeping the code stub.
124   // These methods should not be called with undefined or null.
125   static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object);
126   // TODO(verwaest): This currently returns a HeapObject rather than JSObject*
127   // since loading the IC for loading the length from strings are stored on
128   // the string map directly, rather than on the JSObject-typed prototype.
129   static inline HeapObject* GetCodeCacheHolder(Isolate* isolate,
130                                                Object* object,
131                                                InlineCacheHolderFlag holder);
132
133   static inline InlineCacheHolderFlag GetCodeCacheFlag(HeapType* type);
134   static inline Handle<Map> GetCodeCacheHolder(InlineCacheHolderFlag flag,
135                                                HeapType* type,
136                                                Isolate* isolate);
137
138   static bool IsCleared(Code* code) {
139     InlineCacheState state = code->ic_state();
140     return state == UNINITIALIZED || state == PREMONOMORPHIC;
141   }
142
143   // Utility functions to convert maps to types and back. There are two special
144   // cases:
145   // - The heap_number_map is used as a marker which includes heap numbers as
146   //   well as smis.
147   // - The oddball map is only used for booleans.
148   static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate);
149   static Handle<HeapType> MapToType(Handle<Map> map);
150   static Handle<HeapType> CurrentTypeOf(
151       Handle<Object> object, Isolate* isolate);
152
153  protected:
154   // Get the call-site target; used for determining the state.
155   Handle<Code> target() const { return target_; }
156
157   Address fp() const { return fp_; }
158   Address pc() const { return *pc_address_; }
159   Isolate* isolate() const { return isolate_; }
160
161 #ifdef ENABLE_DEBUGGER_SUPPORT
162   // Computes the address in the original code when the code running is
163   // containing break points (calls to DebugBreakXXX builtins).
164   Address OriginalCodeAddress() const;
165 #endif
166
167   // Set the call-site target.
168   void set_target(Code* code) {
169     SetTargetAtAddress(address(), code);
170     target_set_ = true;
171   }
172
173   bool is_target_set() { return target_set_; }
174
175 #ifdef DEBUG
176   char TransitionMarkFromState(IC::State state);
177
178   void TraceIC(const char* type, Handle<Object> name);
179 #endif
180
181   Failure* TypeError(const char* type,
182                      Handle<Object> object,
183                      Handle<Object> key);
184   Failure* ReferenceError(const char* type, Handle<String> name);
185
186   // Access the target code for the given IC address.
187   static inline Code* GetTargetAtAddress(Address address);
188   static inline void SetTargetAtAddress(Address address, Code* target);
189   static void PostPatching(Address address, Code* target, Code* old_target);
190
191   // Compute the handler either by compiling or by retrieving a cached version.
192   Handle<Code> ComputeHandler(LookupResult* lookup,
193                               Handle<Object> object,
194                               Handle<String> name,
195                               Handle<Object> value = Handle<Code>::null());
196   virtual Handle<Code> CompileHandler(LookupResult* lookup,
197                                       Handle<Object> object,
198                                       Handle<String> name,
199                                       Handle<Object> value,
200                                       InlineCacheHolderFlag cache_holder) {
201     UNREACHABLE();
202     return Handle<Code>::null();
203   }
204
205   void UpdateMonomorphicIC(Handle<HeapType> type,
206                            Handle<Code> handler,
207                            Handle<String> name);
208
209   bool UpdatePolymorphicIC(Handle<HeapType> type,
210                            Handle<String> name,
211                            Handle<Code> code);
212
213   virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
214
215   void CopyICToMegamorphicCache(Handle<String> name);
216   bool IsTransitionOfMonomorphicTarget(Handle<HeapType> type);
217   void PatchCache(Handle<HeapType> type,
218                   Handle<String> name,
219                   Handle<Code> code);
220   virtual Code::Kind kind() const {
221     UNREACHABLE();
222     return Code::STUB;
223   }
224   virtual Handle<Code> slow_stub() const {
225     UNREACHABLE();
226     return Handle<Code>::null();
227   }
228   virtual Handle<Code> megamorphic_stub() {
229     UNREACHABLE();
230     return Handle<Code>::null();
231   }
232   virtual Handle<Code> generic_stub() const {
233     UNREACHABLE();
234     return Handle<Code>::null();
235   }
236
237   bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
238                                               Handle<String> name);
239   void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name);
240
241   ExtraICState extra_ic_state() const { return extra_ic_state_; }
242   void set_extra_ic_state(ExtraICState state) {
243     extra_ic_state_ = state;
244   }
245
246  private:
247   Code* raw_target() const { return GetTargetAtAddress(address()); }
248
249   // Frame pointer for the frame that uses (calls) the IC.
250   Address fp_;
251
252   // All access to the program counter of an IC structure is indirect
253   // to make the code GC safe. This feature is crucial since
254   // GetProperty and SetProperty are called and they in turn might
255   // invoke the garbage collector.
256   Address* pc_address_;
257
258   Isolate* isolate_;
259
260   // The original code target that missed.
261   Handle<Code> target_;
262   State state_;
263   bool target_set_;
264
265   ExtraICState extra_ic_state_;
266
267   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
268 };
269
270
271 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
272 // cannot make forward declarations to an enum.
273 class IC_Utility {
274  public:
275   explicit IC_Utility(IC::UtilityId id)
276     : address_(IC::AddressFromUtilityId(id)), id_(id) {}
277
278   Address address() const { return address_; }
279
280   IC::UtilityId id() const { return id_; }
281  private:
282   Address address_;
283   IC::UtilityId id_;
284 };
285
286
287 class CallICBase: public IC {
288  public:
289   // Returns a JSFunction or a Failure.
290   MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
291                                             Handle<String> name);
292
293  protected:
294   CallICBase(Code::Kind kind, Isolate* isolate)
295       : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
296
297   // Compute a monomorphic stub if possible, otherwise return a null handle.
298   Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
299                                       Handle<Object> object,
300                                       Handle<String> name);
301
302   // Update the inline cache and the global stub cache based on the lookup
303   // result.
304   void UpdateCaches(LookupResult* lookup,
305                     Handle<Object> object,
306                     Handle<String> name);
307
308   // Returns a JSFunction if the object can be called as a function, and
309   // patches the stack to be ready for the call.  Otherwise, it returns the
310   // undefined value.
311   Handle<Object> TryCallAsFunction(Handle<Object> object);
312
313   void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
314
315   static void Clear(Address address, Code* target);
316
317   // Platform-specific code generation functions used by both call and
318   // keyed call.
319   static void GenerateMiss(MacroAssembler* masm,
320                            int argc,
321                            IC::UtilityId id,
322                            ExtraICState extra_state);
323
324   static void GenerateNormal(MacroAssembler* masm, int argc);
325
326   static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
327                                             int argc,
328                                             Code::Kind kind,
329                                             ExtraICState extra_state);
330
331   virtual Handle<Code> megamorphic_stub();
332   virtual Handle<Code> pre_monomorphic_stub();
333
334   Code::Kind kind_;
335
336   friend class IC;
337 };
338
339
340 class CallIC: public CallICBase {
341  public:
342   explicit CallIC(Isolate* isolate)
343       : CallICBase(Code::CALL_IC, isolate) {
344     ASSERT(target()->is_call_stub());
345   }
346
347   // Code generator routines.
348   static void GenerateInitialize(MacroAssembler* masm,
349                                  int argc,
350                                  ExtraICState extra_state) {
351     GenerateMiss(masm, argc, extra_state);
352   }
353
354   static void GenerateMiss(MacroAssembler* masm,
355                            int argc,
356                            ExtraICState extra_state) {
357     CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
358   }
359
360   static void GenerateMegamorphic(MacroAssembler* masm,
361                                   int argc,
362                                   ExtraICState extra_ic_state);
363
364   static void GenerateNormal(MacroAssembler* masm, int argc) {
365     CallICBase::GenerateNormal(masm, argc);
366     GenerateMiss(masm, argc, kNoExtraICState);
367   }
368   bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object);
369 };
370
371
372 class KeyedCallIC: public CallICBase {
373  public:
374   explicit KeyedCallIC(Isolate* isolate)
375       : CallICBase(Code::KEYED_CALL_IC, isolate) {
376     ASSERT(target()->is_keyed_call_stub());
377   }
378
379   MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
380                                             Handle<Object> key);
381
382   // Code generator routines.
383   static void GenerateInitialize(MacroAssembler* masm, int argc) {
384     GenerateMiss(masm, argc);
385   }
386
387   static void GenerateMiss(MacroAssembler* masm, int argc) {
388     CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
389                              kNoExtraICState);
390   }
391
392   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
393   static void GenerateNormal(MacroAssembler* masm, int argc);
394   static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
395 };
396
397
398 class LoadIC: public IC {
399  public:
400   // ExtraICState bits
401   class Contextual: public BitField<ContextualMode, 0, 1> {};
402   STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
403
404   static ExtraICState ComputeExtraICState(ContextualMode mode) {
405     return Contextual::encode(mode);
406   }
407
408   static ContextualMode GetContextualMode(ExtraICState state) {
409     return Contextual::decode(state);
410   }
411
412   ContextualMode contextual_mode() const {
413     return Contextual::decode(extra_ic_state());
414   }
415
416   explicit LoadIC(FrameDepth depth, Isolate* isolate)
417       : IC(depth, isolate) {
418     ASSERT(IsLoadStub());
419   }
420
421   // Returns if this IC is for contextual (no explicit receiver)
422   // access to properties.
423   bool IsUndeclaredGlobal(Handle<Object> receiver) {
424     if (receiver->IsGlobalObject()) {
425       return contextual_mode() == CONTEXTUAL;
426     } else {
427       ASSERT(contextual_mode() != CONTEXTUAL);
428       return false;
429     }
430   }
431
432   // Code generator routines.
433   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
434   static void GeneratePreMonomorphic(MacroAssembler* masm) {
435     GenerateMiss(masm);
436   }
437   static void GenerateMiss(MacroAssembler* masm);
438   static void GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode);
439   static void GenerateNormal(MacroAssembler* masm);
440   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
441
442   static Handle<Code> initialize_stub(Isolate* isolate, ContextualMode mode);
443
444   MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
445                                     Handle<String> name);
446
447  protected:
448   virtual Code::Kind kind() const { return Code::LOAD_IC; }
449
450   void set_target(Code* code) {
451     // The contextual mode must be preserved across IC patching.
452     ASSERT(GetContextualMode(code->extra_ic_state()) ==
453            GetContextualMode(target()->extra_ic_state()));
454
455     IC::set_target(code);
456   }
457
458   virtual Handle<Code> slow_stub() const {
459     return isolate()->builtins()->LoadIC_Slow();
460   }
461
462   virtual Handle<Code> megamorphic_stub();
463
464   // Update the inline cache and the global stub cache based on the
465   // lookup result.
466   void UpdateCaches(LookupResult* lookup,
467                     Handle<Object> object,
468                     Handle<String> name);
469
470   virtual Handle<Code> CompileHandler(LookupResult* lookup,
471                                       Handle<Object> object,
472                                       Handle<String> name,
473                                       Handle<Object> unused,
474                                       InlineCacheHolderFlag cache_holder);
475
476  private:
477   // Stub accessors.
478   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
479                                            ContextualMode mode);
480
481   virtual Handle<Code> pre_monomorphic_stub() {
482     return pre_monomorphic_stub(isolate(), contextual_mode());
483   }
484
485   Handle<Code> SimpleFieldLoad(int offset,
486                                bool inobject = true,
487                                Representation representation =
488                                     Representation::Tagged());
489
490   static void Clear(Isolate* isolate, Address address, Code* target);
491
492   friend class IC;
493 };
494
495
496 class KeyedLoadIC: public LoadIC {
497  public:
498   explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate)
499       : LoadIC(depth, isolate) {
500     ASSERT(target()->is_keyed_load_stub());
501   }
502
503   MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
504                                     Handle<Object> key);
505
506   // Code generator routines.
507   static void GenerateMiss(MacroAssembler* masm);
508   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
509   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
510   static void GeneratePreMonomorphic(MacroAssembler* masm) {
511     GenerateMiss(masm);
512   }
513   static void GenerateGeneric(MacroAssembler* masm);
514   static void GenerateString(MacroAssembler* masm);
515   static void GenerateIndexedInterceptor(MacroAssembler* masm);
516   static void GenerateNonStrictArguments(MacroAssembler* masm);
517
518   // Bit mask to be tested against bit field for the cases when
519   // generic stub should go into slow case.
520   // Access check is necessary explicitly since generic stub does not perform
521   // map checks.
522   static const int kSlowCaseBitFieldMask =
523       (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
524
525  protected:
526   virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
527
528   Handle<Code> LoadElementStub(Handle<JSObject> receiver);
529
530   virtual Handle<Code> megamorphic_stub() {
531     return isolate()->builtins()->KeyedLoadIC_Generic();
532   }
533   virtual Handle<Code> generic_stub() const {
534     return isolate()->builtins()->KeyedLoadIC_Generic();
535   }
536   virtual Handle<Code> slow_stub() const {
537     return isolate()->builtins()->KeyedLoadIC_Slow();
538   }
539
540   virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {}
541
542  private:
543   // Stub accessors.
544   static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
545     return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
546   }
547   virtual Handle<Code> pre_monomorphic_stub() {
548     return pre_monomorphic_stub(isolate());
549   }
550   Handle<Code> indexed_interceptor_stub() {
551     return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
552   }
553   Handle<Code> non_strict_arguments_stub() {
554     return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
555   }
556   Handle<Code> string_stub() {
557     return isolate()->builtins()->KeyedLoadIC_String();
558   }
559
560   static void Clear(Isolate* isolate, Address address, Code* target);
561
562   friend class IC;
563 };
564
565
566 class StoreIC: public IC {
567  public:
568   class StrictModeState: public BitField<StrictModeFlag, 1, 1> {};
569   static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
570     return StrictModeState::encode(flag);
571   }
572
573   static StrictModeFlag GetStrictMode(ExtraICState state) {
574     return StrictModeState::decode(state);
575   }
576
577   // For convenience, a statically declared encoding of strict mode extra
578   // IC state.
579   static const ExtraICState kStrictModeState =
580       1 << StrictModeState::kShift;
581
582   StoreIC(FrameDepth depth, Isolate* isolate)
583       : IC(depth, isolate) {
584     ASSERT(IsStoreStub());
585   }
586
587   StrictModeFlag strict_mode() const {
588     return StrictModeState::decode(extra_ic_state());
589   }
590
591   // Code generators for stub routines. Only called once at startup.
592   static void GenerateSlow(MacroAssembler* masm);
593   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
594   static void GeneratePreMonomorphic(MacroAssembler* masm) {
595     GenerateMiss(masm);
596   }
597   static void GenerateMiss(MacroAssembler* masm);
598   static void GenerateMegamorphic(MacroAssembler* masm,
599                                   ExtraICState extra_ic_state);
600   static void GenerateNormal(MacroAssembler* masm);
601   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
602                                          StrictModeFlag strict_mode);
603
604   static Handle<Code> initialize_stub(Isolate* isolate,
605                                       StrictModeFlag strict_mode);
606
607   MUST_USE_RESULT MaybeObject* Store(
608       Handle<Object> object,
609       Handle<String> name,
610       Handle<Object> value,
611       JSReceiver::StoreFromKeyed store_mode =
612           JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
613
614  protected:
615   virtual Code::Kind kind() const { return Code::STORE_IC; }
616   virtual Handle<Code> megamorphic_stub();
617
618   // Stub accessors.
619   virtual Handle<Code> generic_stub() const;
620
621   virtual Handle<Code> slow_stub() const {
622     return isolate()->builtins()->StoreIC_Slow();
623   }
624
625   virtual Handle<Code> pre_monomorphic_stub() {
626     return pre_monomorphic_stub(isolate(), strict_mode());
627   }
628
629   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
630                                            StrictModeFlag strict_mode);
631
632   // Update the inline cache and the global stub cache based on the
633   // lookup result.
634   void UpdateCaches(LookupResult* lookup,
635                     Handle<JSObject> receiver,
636                     Handle<String> name,
637                     Handle<Object> value);
638   virtual Handle<Code> CompileHandler(LookupResult* lookup,
639                                       Handle<Object> object,
640                                       Handle<String> name,
641                                       Handle<Object> value,
642                                       InlineCacheHolderFlag cache_holder);
643
644  private:
645   void set_target(Code* code) {
646     // Strict mode must be preserved across IC patching.
647     ASSERT(GetStrictMode(code->extra_ic_state()) ==
648            GetStrictMode(target()->extra_ic_state()));
649     IC::set_target(code);
650   }
651
652   static void Clear(Isolate* isolate, Address address, Code* target);
653
654   friend class IC;
655 };
656
657
658 enum KeyedStoreCheckMap {
659   kDontCheckMap,
660   kCheckMap
661 };
662
663
664 enum KeyedStoreIncrementLength {
665   kDontIncrementLength,
666   kIncrementLength
667 };
668
669
670 class KeyedStoreIC: public StoreIC {
671  public:
672   // ExtraICState bits (building on IC)
673   // ExtraICState bits
674   class ExtraICStateKeyedAccessStoreMode:
675       public BitField<KeyedAccessStoreMode, 2, 4> {};  // NOLINT
676
677   static ExtraICState ComputeExtraICState(StrictModeFlag flag,
678                                           KeyedAccessStoreMode mode) {
679     return StrictModeState::encode(flag) |
680         ExtraICStateKeyedAccessStoreMode::encode(mode);
681   }
682
683   static KeyedAccessStoreMode GetKeyedAccessStoreMode(
684       ExtraICState extra_state) {
685     return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
686   }
687
688   KeyedStoreIC(FrameDepth depth, Isolate* isolate)
689       : StoreIC(depth, isolate) {
690     ASSERT(target()->is_keyed_store_stub());
691   }
692
693   MUST_USE_RESULT MaybeObject* Store(Handle<Object> object,
694                                      Handle<Object> name,
695                                      Handle<Object> value);
696
697   // Code generators for stub routines.  Only called once at startup.
698   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
699   static void GeneratePreMonomorphic(MacroAssembler* masm) {
700     GenerateMiss(masm);
701   }
702   static void GenerateMiss(MacroAssembler* masm);
703   static void GenerateSlow(MacroAssembler* masm);
704   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
705                                          StrictModeFlag strict_mode);
706   static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
707   static void GenerateNonStrictArguments(MacroAssembler* masm);
708
709  protected:
710   virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
711
712   virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {}
713
714   virtual Handle<Code> pre_monomorphic_stub() {
715     return pre_monomorphic_stub(isolate(), strict_mode());
716   }
717   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
718                                            StrictModeFlag strict_mode) {
719     if (strict_mode == kStrictMode) {
720       return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
721     } else {
722       return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
723     }
724   }
725   virtual Handle<Code> slow_stub() const {
726     return isolate()->builtins()->KeyedStoreIC_Slow();
727   }
728   virtual Handle<Code> megamorphic_stub() {
729     if (strict_mode() == kStrictMode) {
730       return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
731     } else {
732       return isolate()->builtins()->KeyedStoreIC_Generic();
733     }
734   }
735
736   Handle<Code> StoreElementStub(Handle<JSObject> receiver,
737                                 KeyedAccessStoreMode store_mode);
738
739  private:
740   void set_target(Code* code) {
741     // Strict mode must be preserved across IC patching.
742     ASSERT(GetStrictMode(code->extra_ic_state()) == strict_mode());
743     IC::set_target(code);
744   }
745
746   // Stub accessors.
747   virtual Handle<Code> generic_stub() const {
748     if (strict_mode() == kStrictMode) {
749       return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
750     } else {
751       return isolate()->builtins()->KeyedStoreIC_Generic();
752     }
753   }
754
755   Handle<Code> non_strict_arguments_stub() {
756     return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
757   }
758
759   static void Clear(Isolate* isolate, Address address, Code* target);
760
761   KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
762                                     Handle<Object> key,
763                                     Handle<Object> value);
764
765   Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
766                                      KeyedAccessStoreMode store_mode);
767
768   friend class IC;
769 };
770
771
772 // Mode to overwrite BinaryExpression values.
773 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
774
775 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
776 class BinaryOpIC: public IC {
777  public:
778   class State V8_FINAL BASE_EMBEDDED {
779    public:
780     explicit State(ExtraICState extra_ic_state);
781
782     State(Token::Value op, OverwriteMode mode)
783         : op_(op), mode_(mode), left_kind_(NONE), right_kind_(NONE),
784           result_kind_(NONE) {
785       ASSERT_LE(FIRST_TOKEN, op);
786       ASSERT_LE(op, LAST_TOKEN);
787     }
788
789     InlineCacheState GetICState() const {
790       if (Max(left_kind_, right_kind_) == NONE) {
791         return ::v8::internal::UNINITIALIZED;
792       }
793       if (Max(left_kind_, right_kind_) == GENERIC) {
794         return ::v8::internal::MEGAMORPHIC;
795       }
796       if (Min(left_kind_, right_kind_) == GENERIC) {
797         return ::v8::internal::GENERIC;
798       }
799       return ::v8::internal::MONOMORPHIC;
800     }
801
802     ExtraICState GetExtraICState() const;
803
804     static void GenerateAheadOfTime(
805         Isolate*, void (*Generate)(Isolate*, const State&));
806
807     bool CanReuseDoubleBox() const {
808       return (result_kind_ > SMI && result_kind_ <= NUMBER) &&
809           ((mode_ == OVERWRITE_LEFT &&
810             left_kind_ > SMI && left_kind_ <= NUMBER) ||
811            (mode_ == OVERWRITE_RIGHT &&
812             right_kind_ > SMI && right_kind_ <= NUMBER));
813     }
814
815     // Returns true if the IC _could_ create allocation mementos.
816     bool CouldCreateAllocationMementos() const {
817       if (left_kind_ == STRING || right_kind_ == STRING) {
818         ASSERT_EQ(Token::ADD, op_);
819         return true;
820       }
821       return false;
822     }
823
824     // Returns true if the IC _should_ create allocation mementos.
825     bool ShouldCreateAllocationMementos() const {
826       return FLAG_allocation_site_pretenuring &&
827           CouldCreateAllocationMementos();
828     }
829
830     bool HasSideEffects() const {
831       return Max(left_kind_, right_kind_) == GENERIC;
832     }
833
834     // Returns true if the IC should enable the inline smi code (i.e. if either
835     // parameter may be a smi).
836     bool UseInlinedSmiCode() const {
837       return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
838     }
839
840     static const int FIRST_TOKEN = Token::BIT_OR;
841     static const int LAST_TOKEN = Token::MOD;
842
843     Token::Value op() const { return op_; }
844     OverwriteMode mode() const { return mode_; }
845     Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
846
847     Type* GetLeftType(Zone* zone) const {
848       return KindToType(left_kind_, zone);
849     }
850     Type* GetRightType(Zone* zone) const {
851       return KindToType(right_kind_, zone);
852     }
853     Type* GetResultType(Zone* zone) const;
854
855     void Print(StringStream* stream) const;
856
857     void Update(Handle<Object> left,
858                 Handle<Object> right,
859                 Handle<Object> result);
860
861    private:
862     enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
863
864     Kind UpdateKind(Handle<Object> object, Kind kind) const;
865
866     static const char* KindToString(Kind kind);
867     static Type* KindToType(Kind kind, Zone* zone);
868     static bool KindMaybeSmi(Kind kind) {
869       return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
870     }
871
872     // We truncate the last bit of the token.
873     STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
874     class OpField:                 public BitField<int, 0, 4> {};
875     class OverwriteModeField:      public BitField<OverwriteMode, 4, 2> {};
876     class SSE2Field:               public BitField<bool, 6, 1> {};
877     class ResultKindField:         public BitField<Kind, 7, 3> {};
878     class LeftKindField:           public BitField<Kind, 10,  3> {};
879     // When fixed right arg is set, we don't need to store the right kind.
880     // Thus the two fields can overlap.
881     class HasFixedRightArgField:   public BitField<bool, 13, 1> {};
882     class FixedRightArgValueField: public BitField<int,  14, 4> {};
883     class RightKindField:          public BitField<Kind, 14, 3> {};
884
885     Token::Value op_;
886     OverwriteMode mode_;
887     Kind left_kind_;
888     Kind right_kind_;
889     Kind result_kind_;
890     Maybe<int> fixed_right_arg_;
891   };
892
893   explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
894
895   static Builtins::JavaScript TokenToJSBuiltin(Token::Value op);
896
897   MaybeObject* Transition(Handle<AllocationSite> allocation_site,
898                           Handle<Object> left,
899                           Handle<Object> right) V8_WARN_UNUSED_RESULT;
900 };
901
902
903 class CompareIC: public IC {
904  public:
905   // The type/state lattice is defined by the following inequations:
906   //   UNINITIALIZED < ...
907   //   ... < GENERIC
908   //   SMI < NUMBER
909   //   INTERNALIZED_STRING < STRING
910   //   KNOWN_OBJECT < OBJECT
911   enum State {
912     UNINITIALIZED,
913     SMI,
914     NUMBER,
915     STRING,
916     INTERNALIZED_STRING,
917     UNIQUE_NAME,    // Symbol or InternalizedString
918     OBJECT,         // JSObject
919     KNOWN_OBJECT,   // JSObject with specific map (faster check)
920     GENERIC
921   };
922
923   static State NewInputState(State old_state, Handle<Object> value);
924
925   static Type* StateToType(Zone* zone,
926                            State state,
927                            Handle<Map> map = Handle<Map>());
928
929   static void StubInfoToType(int stub_minor_key,
930                              Type** left_type,
931                              Type** right_type,
932                              Type** overall_type,
933                              Handle<Map> map,
934                              Zone* zone);
935
936   CompareIC(Isolate* isolate, Token::Value op)
937       : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
938
939   // Update the inline cache for the given operands.
940   Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
941
942
943   // Factory method for getting an uninitialized compare stub.
944   static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op);
945
946   // Helper function for computing the condition for a compare operation.
947   static Condition ComputeCondition(Token::Value op);
948
949   static const char* GetStateName(State state);
950
951  private:
952   static bool HasInlinedSmiCode(Address address);
953
954   State TargetState(State old_state,
955                     State old_left,
956                     State old_right,
957                     bool has_inlined_smi_code,
958                     Handle<Object> x,
959                     Handle<Object> y);
960
961   bool strict() const { return op_ == Token::EQ_STRICT; }
962   Condition GetCondition() const { return ComputeCondition(op_); }
963
964   static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
965
966   static void Clear(Isolate* isolate, Address address, Code* target);
967
968   Token::Value op_;
969
970   friend class IC;
971 };
972
973
974 class CompareNilIC: public IC {
975  public:
976   explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
977
978   MUST_USE_RESULT MaybeObject* CompareNil(Handle<Object> object);
979
980   static Handle<Code> GetUninitialized();
981
982   static void Clear(Address address, Code* target);
983
984   static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(NilValue nil,
985                                                        Handle<Object> object);
986 };
987
988
989 class ToBooleanIC: public IC {
990  public:
991   explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
992
993   MaybeObject* ToBoolean(Handle<Object> object);
994 };
995
996
997 // Helper for BinaryOpIC and CompareIC.
998 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
999 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
1000
1001 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
1002 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
1003 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
1004 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
1005 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure);
1006 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
1007 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss);
1008 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite);
1009 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
1010 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
1011
1012
1013 } }  // namespace v8::internal
1014
1015 #endif  // V8_IC_H_