8c1c82eac7059dfbb31128a6d934d0dbc89c4a3c
[platform/upstream/nodejs.git] / deps / v8 / src / ic / ic.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_IC_H_
6 #define V8_IC_H_
7
8 #include "src/ic/ic-state.h"
9 #include "src/macro-assembler.h"
10
11 namespace v8 {
12 namespace internal {
13
14
15 // IC_UTIL_LIST defines all utility functions called from generated
16 // inline caching code. The argument for the macro, ICU, is the function name.
17 #define IC_UTIL_LIST(ICU)              \
18   ICU(LoadIC_Miss)                     \
19   ICU(KeyedLoadIC_Miss)                \
20   ICU(CallIC_Miss)                     \
21   ICU(CallIC_Customization_Miss)       \
22   ICU(StoreIC_Miss)                    \
23   ICU(StoreIC_Slow)                    \
24   ICU(KeyedStoreIC_Miss)               \
25   ICU(KeyedStoreIC_Slow)               \
26   /* Utilities for IC stubs. */        \
27   ICU(StoreCallbackProperty)           \
28   ICU(LoadPropertyWithInterceptorOnly) \
29   ICU(LoadPropertyWithInterceptor)     \
30   ICU(LoadElementWithInterceptor)      \
31   ICU(StorePropertyWithInterceptor)    \
32   ICU(CompareIC_Miss)                  \
33   ICU(BinaryOpIC_Miss)                 \
34   ICU(CompareNilIC_Miss)               \
35   ICU(Unreachable)                     \
36   ICU(ToBooleanIC_Miss)
37 //
38 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
39 //
40 class IC {
41  public:
42   // The ids for utility called from the generated code.
43   enum UtilityId {
44 #define CONST_NAME(name) k##name,
45     IC_UTIL_LIST(CONST_NAME)
46 #undef CONST_NAME
47     kUtilityCount
48   };
49
50   // Looks up the address of the named utility.
51   static Address AddressFromUtilityId(UtilityId id);
52
53   // Alias the inline cache state type to make the IC code more readable.
54   typedef InlineCacheState State;
55
56   // The IC code is either invoked with no extra frames on the stack
57   // or with a single extra frame for supporting calls.
58   enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 };
59
60   // Construct the IC structure with the given number of extra
61   // JavaScript frames on the stack.
62   IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL,
63      bool for_queries_only = false);
64   virtual ~IC() {}
65
66   State state() const { return state_; }
67   inline Address address() const;
68
69   // Compute the current IC state based on the target stub, receiver and name.
70   void UpdateState(Handle<Object> receiver, Handle<Object> name);
71
72   bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name);
73   void MarkPrototypeFailure(Handle<Object> name) {
74     DCHECK(IsNameCompatibleWithPrototypeFailure(name));
75     old_state_ = state_;
76     state_ = PROTOTYPE_FAILURE;
77   }
78
79   // Clear the inline cache to initial state.
80   static void Clear(Isolate* isolate, Address address,
81                     ConstantPoolArray* constant_pool);
82
83 #ifdef DEBUG
84   bool IsLoadStub() const {
85     return target()->is_load_stub() || target()->is_keyed_load_stub();
86   }
87
88   bool IsStoreStub() const {
89     return target()->is_store_stub() || target()->is_keyed_store_stub();
90   }
91
92   bool IsCallStub() const { return target()->is_call_stub(); }
93 #endif
94
95   static inline JSFunction* GetRootConstructor(Map* receiver_map,
96                                                Context* native_context);
97   static inline Handle<Map> GetHandlerCacheHolder(Handle<Map> receiver_map,
98                                                   bool receiver_is_holder,
99                                                   Isolate* isolate,
100                                                   CacheHolderFlag* flag);
101   static inline Handle<Map> GetICCacheHolder(Handle<Map> receiver_map,
102                                              Isolate* isolate,
103                                              CacheHolderFlag* flag);
104
105   static bool IsCleared(Code* code) {
106     InlineCacheState state = code->ic_state();
107     return state == UNINITIALIZED || state == PREMONOMORPHIC;
108   }
109
110   static bool IsCleared(FeedbackNexus* nexus) {
111     InlineCacheState state = nexus->StateFromFeedback();
112     return state == UNINITIALIZED || state == PREMONOMORPHIC;
113   }
114
115   static bool ICUseVector(Code::Kind kind) {
116     return (FLAG_vector_ics &&
117             (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC)) ||
118            kind == Code::CALL_IC;
119   }
120
121  protected:
122   // Get the call-site target; used for determining the state.
123   Handle<Code> target() const { return target_; }
124
125   Address fp() const { return fp_; }
126   Address pc() const { return *pc_address_; }
127   Isolate* isolate() const { return isolate_; }
128
129   // Get the shared function info of the caller.
130   SharedFunctionInfo* GetSharedFunctionInfo() const;
131   // Get the code object of the caller.
132   Code* GetCode() const;
133   // Get the original (non-breakpointed) code object of the caller.
134   Code* GetOriginalCode() const;
135
136   bool AddressIsOptimizedCode() const;
137
138   // Set the call-site target.
139   inline void set_target(Code* code);
140   bool is_target_set() { return target_set_; }
141   bool is_vector_set() { return vector_set_; }
142
143   bool UseVector() const {
144     bool use = ICUseVector(kind());
145     // If we are supposed to use the nexus, verify the nexus is non-null.
146     DCHECK(!use || nexus_ != NULL);
147     return use;
148   }
149
150   // Configure for most states.
151   void ConfigureVectorState(IC::State new_state);
152   // Configure the vector for MONOMORPHIC.
153   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
154                             Handle<Code> handler);
155   // Configure the vector for POLYMORPHIC.
156   void ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
157                             CodeHandleList* handlers);
158
159   char TransitionMarkFromState(IC::State state);
160   void TraceIC(const char* type, Handle<Object> name);
161   void TraceIC(const char* type, Handle<Object> name, State old_state,
162                State new_state);
163
164   MaybeHandle<Object> TypeError(const char* type, Handle<Object> object,
165                                 Handle<Object> key);
166   MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name);
167
168   // Access the target code for the given IC address.
169   static inline Code* GetTargetAtAddress(Address address,
170                                          ConstantPoolArray* constant_pool);
171   static inline void SetTargetAtAddress(Address address, Code* target,
172                                         ConstantPoolArray* constant_pool);
173   static void OnTypeFeedbackChanged(Isolate* isolate, Address address,
174                                     State old_state, State new_state,
175                                     bool target_remains_ic_stub);
176   // As a vector-based IC, type feedback must be updated differently.
177   static void OnTypeFeedbackChanged(Isolate* isolate, Code* host,
178                                     TypeFeedbackVector* vector, State old_state,
179                                     State new_state);
180   static void PostPatching(Address address, Code* target, Code* old_target);
181
182   // Compute the handler either by compiling or by retrieving a cached version.
183   Handle<Code> ComputeHandler(LookupIterator* lookup,
184                               Handle<Object> value = Handle<Code>::null());
185   virtual Handle<Code> CompileHandler(LookupIterator* lookup,
186                                       Handle<Object> value,
187                                       CacheHolderFlag cache_holder) {
188     UNREACHABLE();
189     return Handle<Code>::null();
190   }
191
192   void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name);
193   bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code);
194   void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
195
196   void CopyICToMegamorphicCache(Handle<Name> name);
197   bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
198   void PatchCache(Handle<Name> name, Handle<Code> code);
199   Code::Kind kind() const { return kind_; }
200   Code::Kind handler_kind() const {
201     if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC;
202     DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC ||
203            kind_ == Code::KEYED_STORE_IC);
204     return kind_;
205   }
206   virtual Handle<Code> megamorphic_stub() {
207     UNREACHABLE();
208     return Handle<Code>::null();
209   }
210
211   bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
212                                               Handle<String> name);
213
214   ExtraICState extra_ic_state() const { return extra_ic_state_; }
215   void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; }
216
217   Handle<Map> receiver_map() { return receiver_map_; }
218   void update_receiver_map(Handle<Object> receiver) {
219     if (receiver->IsSmi()) {
220       receiver_map_ = isolate_->factory()->heap_number_map();
221     } else {
222       receiver_map_ = handle(HeapObject::cast(*receiver)->map());
223     }
224   }
225
226   void TargetMaps(MapHandleList* list) {
227     FindTargetMaps();
228     for (int i = 0; i < target_maps_.length(); i++) {
229       list->Add(target_maps_.at(i));
230     }
231   }
232
233   Map* FirstTargetMap() {
234     FindTargetMaps();
235     return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
236   }
237
238   inline void UpdateTarget();
239
240   Handle<TypeFeedbackVector> vector() const { return nexus()->vector_handle(); }
241   FeedbackVectorICSlot slot() const { return nexus()->slot(); }
242   State saved_state() const {
243     return state() == PROTOTYPE_FAILURE ? old_state_ : state();
244   }
245
246   template <class NexusClass>
247   NexusClass* casted_nexus() {
248     return static_cast<NexusClass*>(nexus_);
249   }
250   FeedbackNexus* nexus() const { return nexus_; }
251
252   inline Code* get_host();
253
254  private:
255   inline Code* raw_target() const;
256   inline ConstantPoolArray* constant_pool() const;
257   inline ConstantPoolArray* raw_constant_pool() const;
258
259   void FindTargetMaps() {
260     if (target_maps_set_) return;
261     target_maps_set_ = true;
262     if (UseVector()) {
263       nexus()->ExtractMaps(&target_maps_);
264     } else {
265       if (state_ == MONOMORPHIC) {
266         Map* map = target_->FindFirstMap();
267         if (map != NULL) target_maps_.Add(handle(map));
268       } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) {
269         target_->FindAllMaps(&target_maps_);
270       }
271     }
272   }
273
274   // Frame pointer for the frame that uses (calls) the IC.
275   Address fp_;
276
277   // All access to the program counter of an IC structure is indirect
278   // to make the code GC safe. This feature is crucial since
279   // GetProperty and SetProperty are called and they in turn might
280   // invoke the garbage collector.
281   Address* pc_address_;
282
283   Isolate* isolate_;
284
285   // The constant pool of the code which originally called the IC (which might
286   // be for the breakpointed copy of the original code).
287   Handle<ConstantPoolArray> raw_constant_pool_;
288
289   // The original code target that missed.
290   Handle<Code> target_;
291   bool target_set_;
292   bool vector_set_;
293   State old_state_;  // For saving if we marked as prototype failure.
294   State state_;
295   Code::Kind kind_;
296   Handle<Map> receiver_map_;
297   MaybeHandle<Code> maybe_handler_;
298
299   ExtraICState extra_ic_state_;
300   MapHandleList target_maps_;
301   bool target_maps_set_;
302
303   FeedbackNexus* nexus_;
304
305   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
306 };
307
308
309 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you
310 // cannot make forward declarations to an enum.
311 class IC_Utility {
312  public:
313   explicit IC_Utility(IC::UtilityId id)
314       : address_(IC::AddressFromUtilityId(id)), id_(id) {}
315
316   Address address() const { return address_; }
317
318   IC::UtilityId id() const { return id_; }
319
320  private:
321   Address address_;
322   IC::UtilityId id_;
323 };
324
325
326 class CallIC : public IC {
327  public:
328   CallIC(Isolate* isolate, CallICNexus* nexus)
329       : IC(EXTRA_CALL_FRAME, isolate, nexus) {
330     DCHECK(nexus != NULL);
331   }
332
333   void PatchMegamorphic(Handle<Object> function);
334
335   void HandleMiss(Handle<Object> function);
336
337   // Returns true if a custom handler was installed.
338   bool DoCustomHandler(Handle<Object> function,
339                        const CallICState& callic_state);
340
341   // Code generator routines.
342   static Handle<Code> initialize_stub(Isolate* isolate, int argc,
343                                       CallICState::CallType call_type);
344   static Handle<Code> initialize_stub_in_optimized_code(
345       Isolate* isolate, int argc, CallICState::CallType call_type);
346
347   static void Clear(Isolate* isolate, Code* host, CallICNexus* nexus);
348 };
349
350
351 class LoadIC : public IC {
352  public:
353   static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) {
354     return LoadICState(contextual_mode).GetExtraICState();
355   }
356
357   ContextualMode contextual_mode() const {
358     return LoadICState::GetContextualMode(extra_ic_state());
359   }
360
361   LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
362       : IC(depth, isolate, nexus) {
363     DCHECK(!FLAG_vector_ics || nexus != NULL);
364     DCHECK(IsLoadStub());
365   }
366
367   // TODO(mvstanton): The for_queries_only is because we have a case where we
368   // construct an IC only to gather the contextual mode, and we don't have
369   // vector/slot information. for_queries_only is a temporary hack to enable the
370   // strong DCHECK protection around vector/slot.
371   LoadIC(FrameDepth depth, Isolate* isolate, bool for_queries_only)
372       : IC(depth, isolate, NULL, for_queries_only) {
373     DCHECK(IsLoadStub());
374   }
375
376   // Returns if this IC is for contextual (no explicit receiver)
377   // access to properties.
378   bool IsUndeclaredGlobal(Handle<Object> receiver) {
379     if (receiver->IsGlobalObject()) {
380       return contextual_mode() == CONTEXTUAL;
381     } else {
382       DCHECK(contextual_mode() != CONTEXTUAL);
383       return false;
384     }
385   }
386
387   // Code generator routines.
388   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
389   static void GeneratePreMonomorphic(MacroAssembler* masm) {
390     GenerateMiss(masm);
391   }
392   static void GenerateMiss(MacroAssembler* masm);
393   static void GenerateNormal(MacroAssembler* masm);
394   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
395
396   static Handle<Code> initialize_stub(Isolate* isolate,
397                                       ExtraICState extra_state);
398   static Handle<Code> initialize_stub_in_optimized_code(
399       Isolate* isolate, ExtraICState extra_state);
400
401   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
402                                            Handle<Name> name);
403
404   static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus);
405
406  protected:
407   inline void set_target(Code* code);
408
409   Handle<Code> slow_stub() const {
410     if (kind() == Code::LOAD_IC) {
411       return isolate()->builtins()->LoadIC_Slow();
412     } else {
413       DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
414       return isolate()->builtins()->KeyedLoadIC_Slow();
415     }
416   }
417
418   Handle<Code> megamorphic_stub() OVERRIDE;
419
420   // Update the inline cache and the global stub cache based on the
421   // lookup result.
422   void UpdateCaches(LookupIterator* lookup);
423
424   virtual Handle<Code> CompileHandler(LookupIterator* lookup,
425                                       Handle<Object> unused,
426                                       CacheHolderFlag cache_holder) OVERRIDE;
427
428  private:
429   virtual Handle<Code> pre_monomorphic_stub() const;
430   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
431                                            ExtraICState extra_state);
432
433   Handle<Code> SimpleFieldLoad(FieldIndex index);
434
435   static void Clear(Isolate* isolate, Address address, Code* target,
436                     ConstantPoolArray* constant_pool);
437
438   friend class IC;
439 };
440
441
442 class KeyedLoadIC : public LoadIC {
443  public:
444   // ExtraICState bits (building on IC)
445   class IcCheckTypeField : public BitField<IcCheckType, 1, 1> {};
446
447   static ExtraICState ComputeExtraICState(ContextualMode contextual_mode,
448                                           IcCheckType key_type) {
449     return LoadICState(contextual_mode).GetExtraICState() |
450            IcCheckTypeField::encode(key_type);
451   }
452
453   static IcCheckType GetKeyType(ExtraICState extra_state) {
454     return IcCheckTypeField::decode(extra_state);
455   }
456
457   KeyedLoadIC(FrameDepth depth, Isolate* isolate,
458               KeyedLoadICNexus* nexus = NULL)
459       : LoadIC(depth, isolate, nexus) {
460     DCHECK(!FLAG_vector_ics || nexus != NULL);
461     DCHECK(target()->is_keyed_load_stub());
462   }
463
464   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
465                                            Handle<Object> key);
466
467   // Code generator routines.
468   static void GenerateMiss(MacroAssembler* masm);
469   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
470   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
471   static void GeneratePreMonomorphic(MacroAssembler* masm) {
472     GenerateMiss(masm);
473   }
474   static void GenerateMegamorphic(MacroAssembler* masm);
475
476   // Bit mask to be tested against bit field for the cases when
477   // generic stub should go into slow case.
478   // Access check is necessary explicitly since generic stub does not perform
479   // map checks.
480   static const int kSlowCaseBitFieldMask =
481       (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
482
483   static Handle<Code> initialize_stub(Isolate* isolate);
484   static Handle<Code> initialize_stub_in_optimized_code(Isolate* isolate);
485   static Handle<Code> ChooseMegamorphicStub(Isolate* isolate);
486   static Handle<Code> pre_monomorphic_stub(Isolate* isolate);
487
488   static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
489
490  protected:
491   // receiver is HeapObject because it could be a String or a JSObject
492   Handle<Code> LoadElementStub(Handle<HeapObject> receiver);
493   virtual Handle<Code> pre_monomorphic_stub() const {
494     return pre_monomorphic_stub(isolate());
495   }
496
497  private:
498   static void Clear(Isolate* isolate, Address address, Code* target,
499                     ConstantPoolArray* constant_pool);
500
501   friend class IC;
502 };
503
504
505 class StoreIC : public IC {
506  public:
507   STATIC_ASSERT(i::LANGUAGE_END == 3);
508   class LanguageModeState : public BitField<LanguageMode, 1, 2> {};
509   static ExtraICState ComputeExtraICState(LanguageMode flag) {
510     return LanguageModeState::encode(flag);
511   }
512   static LanguageMode GetLanguageMode(ExtraICState state) {
513     return LanguageModeState::decode(state);
514   }
515
516   // For convenience, a statically declared encoding of strict mode extra
517   // IC state.
518   static const ExtraICState kStrictModeState = STRICT
519                                                << LanguageModeState::kShift;
520
521   StoreIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
522     DCHECK(IsStoreStub());
523   }
524
525   LanguageMode language_mode() const {
526     return LanguageModeState::decode(extra_ic_state());
527   }
528
529   // Code generators for stub routines. Only called once at startup.
530   static void GenerateSlow(MacroAssembler* masm);
531   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
532   static void GeneratePreMonomorphic(MacroAssembler* masm) {
533     GenerateMiss(masm);
534   }
535   static void GenerateMiss(MacroAssembler* masm);
536   static void GenerateMegamorphic(MacroAssembler* masm);
537   static void GenerateNormal(MacroAssembler* masm);
538   static void GenerateRuntimeSetProperty(MacroAssembler* masm,
539                                          LanguageMode language_mode);
540
541   static Handle<Code> initialize_stub(Isolate* isolate,
542                                       LanguageMode language_mode);
543
544   MUST_USE_RESULT MaybeHandle<Object> Store(
545       Handle<Object> object, Handle<Name> name, Handle<Object> value,
546       JSReceiver::StoreFromKeyed store_mode =
547           JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
548
549   bool LookupForWrite(LookupIterator* it, Handle<Object> value,
550                       JSReceiver::StoreFromKeyed store_mode);
551
552  protected:
553   // Stub accessors.
554   Handle<Code> megamorphic_stub() OVERRIDE;
555   Handle<Code> slow_stub() const;
556
557   virtual Handle<Code> pre_monomorphic_stub() const {
558     return pre_monomorphic_stub(isolate(), language_mode());
559   }
560
561   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
562                                            LanguageMode language_mode);
563
564   // Update the inline cache and the global stub cache based on the
565   // lookup result.
566   void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
567                     JSReceiver::StoreFromKeyed store_mode);
568   virtual Handle<Code> CompileHandler(LookupIterator* lookup,
569                                       Handle<Object> value,
570                                       CacheHolderFlag cache_holder) OVERRIDE;
571
572  private:
573   inline void set_target(Code* code);
574
575   static void Clear(Isolate* isolate, Address address, Code* target,
576                     ConstantPoolArray* constant_pool);
577
578   friend class IC;
579 };
580
581
582 enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
583
584
585 enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
586
587
588 class KeyedStoreIC : public StoreIC {
589  public:
590   // ExtraICState bits (building on IC)
591   // ExtraICState bits
592   // When more language modes are added, these BitFields need to move too.
593   STATIC_ASSERT(i::LANGUAGE_END == 3);
594   class ExtraICStateKeyedAccessStoreMode
595       : public BitField<KeyedAccessStoreMode, 3, 4> {};  // NOLINT
596
597   class IcCheckTypeField : public BitField<IcCheckType, 7, 1> {};
598
599   static ExtraICState ComputeExtraICState(LanguageMode flag,
600                                           KeyedAccessStoreMode mode) {
601     return LanguageModeState::encode(flag) |
602            ExtraICStateKeyedAccessStoreMode::encode(mode) |
603            IcCheckTypeField::encode(ELEMENT);
604   }
605
606   static KeyedAccessStoreMode GetKeyedAccessStoreMode(
607       ExtraICState extra_state) {
608     return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
609   }
610
611   static IcCheckType GetKeyType(ExtraICState extra_state) {
612     return IcCheckTypeField::decode(extra_state);
613   }
614
615   KeyedStoreIC(FrameDepth depth, Isolate* isolate) : StoreIC(depth, isolate) {
616     DCHECK(target()->is_keyed_store_stub());
617   }
618
619   MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
620                                             Handle<Object> name,
621                                             Handle<Object> value);
622
623   // Code generators for stub routines.  Only called once at startup.
624   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
625   static void GeneratePreMonomorphic(MacroAssembler* masm) {
626     GenerateMiss(masm);
627   }
628   static void GenerateMiss(MacroAssembler* masm);
629   static void GenerateSlow(MacroAssembler* masm);
630   static void GenerateMegamorphic(MacroAssembler* masm,
631                                   LanguageMode language_mode);
632   static void GenerateSloppyArguments(MacroAssembler* masm);
633
634  protected:
635   virtual Handle<Code> pre_monomorphic_stub() const {
636     return pre_monomorphic_stub(isolate(), language_mode());
637   }
638   static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
639                                            LanguageMode language_mode) {
640     if (is_strict(language_mode)) {
641       return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
642     } else {
643       return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
644     }
645   }
646
647   Handle<Code> StoreElementStub(Handle<JSObject> receiver,
648                                 KeyedAccessStoreMode store_mode);
649
650  private:
651   inline void set_target(Code* code);
652
653   // Stub accessors.
654   Handle<Code> sloppy_arguments_stub() {
655     return isolate()->builtins()->KeyedStoreIC_SloppyArguments();
656   }
657
658   static void Clear(Isolate* isolate, Address address, Code* target,
659                     ConstantPoolArray* constant_pool);
660
661   KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
662                                     Handle<Object> key, Handle<Object> value);
663
664   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
665                                      KeyedAccessStoreMode store_mode);
666
667   friend class IC;
668 };
669
670
671 // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
672 class BinaryOpIC : public IC {
673  public:
674   explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
675
676   static Builtins::JavaScript TokenToJSBuiltin(Token::Value op);
677
678   MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site,
679                                  Handle<Object> left,
680                                  Handle<Object> right) WARN_UNUSED_RESULT;
681 };
682
683
684 class CompareIC : public IC {
685  public:
686   CompareIC(Isolate* isolate, Token::Value op)
687       : IC(EXTRA_CALL_FRAME, isolate), op_(op) {}
688
689   // Update the inline cache for the given operands.
690   Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
691
692   // Helper function for computing the condition for a compare operation.
693   static Condition ComputeCondition(Token::Value op);
694
695   // Factory method for getting an uninitialized compare stub.
696   static Handle<Code> GetUninitialized(Isolate* isolate, Token::Value op);
697
698  private:
699   static bool HasInlinedSmiCode(Address address);
700
701   bool strict() const { return op_ == Token::EQ_STRICT; }
702   Condition GetCondition() const { return ComputeCondition(op_); }
703
704   static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
705
706   static void Clear(Isolate* isolate, Address address, Code* target,
707                     ConstantPoolArray* constant_pool);
708
709   Token::Value op_;
710
711   friend class IC;
712 };
713
714
715 class CompareNilIC : public IC {
716  public:
717   explicit CompareNilIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
718
719   Handle<Object> CompareNil(Handle<Object> object);
720
721   static Handle<Code> GetUninitialized();
722
723   static void Clear(Address address, Code* target,
724                     ConstantPoolArray* constant_pool);
725
726   static Handle<Object> DoCompareNilSlow(Isolate* isolate, NilValue nil,
727                                          Handle<Object> object);
728 };
729
730
731 class ToBooleanIC : public IC {
732  public:
733   explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
734
735   Handle<Object> ToBoolean(Handle<Object> object);
736 };
737
738
739 // Helper for BinaryOpIC and CompareIC.
740 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
741 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
742
743 DECLARE_RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure);
744 DECLARE_RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure);
745 DECLARE_RUNTIME_FUNCTION(UnaryOpIC_Miss);
746 DECLARE_RUNTIME_FUNCTION(StoreIC_MissFromStubFailure);
747 DECLARE_RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss);
748 DECLARE_RUNTIME_FUNCTION(BinaryOpIC_Miss);
749 DECLARE_RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite);
750 DECLARE_RUNTIME_FUNCTION(CompareNilIC_Miss);
751 DECLARE_RUNTIME_FUNCTION(ToBooleanIC_Miss);
752 DECLARE_RUNTIME_FUNCTION(LoadIC_MissFromStubFailure);
753
754 // Support functions for callbacks handlers.
755 DECLARE_RUNTIME_FUNCTION(StoreCallbackProperty);
756
757 // Support functions for interceptor handlers.
758 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly);
759 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor);
760 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor);
761 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor);
762 }
763 }  // namespace v8::internal
764
765 #endif  // V8_IC_H_