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