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