LCOV - code coverage report
Current view: top level - src/ic - ic.h (source / functions) Hit Total Coverage
Test: app.info Lines: 63 68 92.6 %
Date: 2017-04-26 Functions: 25 40 62.5 %

          Line data    Source code
       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/factory.h"
       9             : #include "src/feedback-vector.h"
      10             : #include "src/ic/ic-state.h"
      11             : #include "src/macro-assembler.h"
      12             : #include "src/messages.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : //
      18             : // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
      19             : //
      20             : class IC {
      21             :  public:
      22             :   // Alias the inline cache state type to make the IC code more readable.
      23             :   typedef InlineCacheState State;
      24             : 
      25             :   // The IC code is either invoked with no extra frames on the stack
      26             :   // or with a single extra frame for supporting calls.
      27             :   enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 };
      28             : 
      29             :   // A polymorphic IC can handle at most 4 distinct maps before transitioning
      30             :   // to megamorphic state.
      31             :   static constexpr int kMaxPolymorphicMapCount = 4;
      32             : 
      33             :   // Construct the IC structure with the given number of extra
      34             :   // JavaScript frames on the stack.
      35             :   IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL);
      36    14598152 :   virtual ~IC() {}
      37             : 
      38             :   State state() const { return state_; }
      39             :   inline Address address() const;
      40             : 
      41             :   // Compute the current IC state based on the target stub, receiver and name.
      42             :   void UpdateState(Handle<Object> receiver, Handle<Object> name);
      43             : 
      44             :   bool RecomputeHandlerForName(Handle<Object> name);
      45             :   void MarkRecomputeHandler(Handle<Object> name) {
      46             :     DCHECK(RecomputeHandlerForName(name));
      47      353770 :     old_state_ = state_;
      48      353770 :     state_ = RECOMPUTE_HANDLER;
      49             :   }
      50             : 
      51             :   // Clear the inline cache to initial state.
      52             :   static void Clear(Isolate* isolate, Address address, Address constant_pool);
      53             : 
      54     1445336 :   bool IsAnyLoad() const {
      55     2427321 :     return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
      56             :   }
      57             :   bool IsAnyStore() const {
      58             :     return IsStoreIC() || IsStoreOwnIC() || IsStoreGlobalIC() ||
      59             :            IsKeyedStoreIC();
      60             :   }
      61             : 
      62             :   // The ICs that don't pass slot and vector through the stack have to
      63             :   // save/restore them in the dispatcher.
      64             :   static bool ShouldPushPopSlotAndVector(Code::Kind kind);
      65             : 
      66             :   static InlineCacheState StateFromCode(Code* code);
      67             : 
      68             :   static inline bool IsHandler(Object* object);
      69             : 
      70             :   // Nofity the IC system that a feedback has changed.
      71             :   static void OnFeedbackChanged(Isolate* isolate, JSFunction* host_function);
      72             : 
      73             :  protected:
      74             :   Address fp() const { return fp_; }
      75     3725653 :   Address pc() const { return *pc_address_; }
      76             : 
      77      228209 :   void set_slow_stub_reason(const char* reason) { slow_stub_reason_ = reason; }
      78             : 
      79             :   Address GetAbstractPC(int* line, int* column) const;
      80             :   Isolate* isolate() const { return isolate_; }
      81             : 
      82             :   // Get the caller function object.
      83             :   JSFunction* GetHostFunction() const;
      84             : 
      85             :   inline bool AddressIsDeoptimizedCode() const;
      86             :   inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
      87             :                                               Address address);
      88             : 
      89             :   // Set the call-site target.
      90             :   inline void set_target(Code* code);
      91             :   bool is_vector_set() { return vector_set_; }
      92             : 
      93             :   // Configure for most states.
      94             :   void ConfigureVectorState(IC::State new_state, Handle<Object> key);
      95             :   // Configure the vector for MONOMORPHIC.
      96             :   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
      97             :                             Handle<Object> handler);
      98             :   // Configure the vector for POLYMORPHIC.
      99             :   void ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
     100             :                             List<Handle<Object>>* handlers);
     101             : 
     102             :   char TransitionMarkFromState(IC::State state);
     103             :   void TraceIC(const char* type, Handle<Object> name);
     104             :   void TraceIC(const char* type, Handle<Object> name, State old_state,
     105             :                State new_state);
     106             : 
     107             :   MaybeHandle<Object> TypeError(MessageTemplate::Template,
     108             :                                 Handle<Object> object, Handle<Object> key);
     109             :   MaybeHandle<Object> ReferenceError(Handle<Name> name);
     110             : 
     111             :   // Access the target code for the given IC address.
     112             :   static inline Code* GetTargetAtAddress(Address address,
     113             :                                          Address constant_pool);
     114             :   static inline void SetTargetAtAddress(Address address, Code* target,
     115             :                                         Address constant_pool);
     116             :   static void PostPatching(Address address, Code* target, Code* old_target);
     117             : 
     118             :   void TraceHandlerCacheHitStats(LookupIterator* lookup);
     119             : 
     120             :   // Compute the handler either by compiling or by retrieving a cached version.
     121             :   Handle<Object> ComputeHandler(LookupIterator* lookup);
     122           0 :   virtual Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) {
     123           0 :     UNREACHABLE();
     124             :     return Handle<Code>::null();
     125             :   }
     126           0 :   virtual Handle<Code> CompileHandler(LookupIterator* lookup) {
     127           0 :     UNREACHABLE();
     128             :     return Handle<Code>::null();
     129             :   }
     130             : 
     131             :   void UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name);
     132             :   bool UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code);
     133             :   void UpdateMegamorphicCache(Map* map, Name* name, Object* code);
     134             : 
     135             :   StubCache* stub_cache();
     136             : 
     137             :   void CopyICToMegamorphicCache(Handle<Name> name);
     138             :   bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
     139             :   void PatchCache(Handle<Name> name, Handle<Object> code);
     140             :   FeedbackSlotKind kind() const { return kind_; }
     141             :   bool IsLoadIC() const { return IsLoadICKind(kind_); }
     142             :   bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
     143             :   bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
     144             :   bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); }
     145             :   bool IsStoreIC() const { return IsStoreICKind(kind_); }
     146             :   bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); }
     147             :   bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
     148    24342670 :   bool is_keyed() const { return IsKeyedLoadIC() || IsKeyedStoreIC(); }
     149             :   Code::Kind handler_kind() const {
     150       41492 :     if (IsAnyLoad()) return Code::LOAD_IC;
     151             :     DCHECK(IsAnyStore());
     152             :     return Code::STORE_IC;
     153             :   }
     154             :   bool ShouldRecomputeHandler(Handle<String> name);
     155             : 
     156             :   ExtraICState extra_ic_state() const { return extra_ic_state_; }
     157             : 
     158             :   Handle<Map> receiver_map() { return receiver_map_; }
     159    18097461 :   void update_receiver_map(Handle<Object> receiver) {
     160    18097461 :     if (receiver->IsSmi()) {
     161       62354 :       receiver_map_ = isolate_->factory()->heap_number_map();
     162             :     } else {
     163    18066283 :       receiver_map_ = handle(HeapObject::cast(*receiver)->map());
     164             :     }
     165    18097460 :   }
     166             : 
     167     2890634 :   void TargetMaps(MapHandleList* list) {
     168             :     FindTargetMaps();
     169     5932921 :     for (int i = 0; i < target_maps_.length(); i++) {
     170     5932921 :       list->Add(target_maps_.at(i));
     171             :     }
     172     2890635 :   }
     173             : 
     174     2084025 :   Map* FirstTargetMap() {
     175             :     FindTargetMaps();
     176     4168050 :     return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
     177             :   }
     178             : 
     179             :   Handle<FeedbackVector> vector() const { return nexus()->vector_handle(); }
     180             :   FeedbackSlot slot() const { return nexus()->slot(); }
     181             :   State saved_state() const {
     182             :     return state() == RECOMPUTE_HANDLER ? old_state_ : state();
     183             :   }
     184             : 
     185             :   template <class NexusClass>
     186             :   NexusClass* casted_nexus() {
     187             :     return static_cast<NexusClass*>(nexus_);
     188             :   }
     189             :   FeedbackNexus* nexus() const { return nexus_; }
     190             : 
     191             :   inline Code* target() const;
     192             : 
     193             :  private:
     194             :   inline Address constant_pool() const;
     195             :   inline Address raw_constant_pool() const;
     196             : 
     197     2868979 :   void FindTargetMaps() {
     198     4974659 :     if (target_maps_set_) return;
     199     2868979 :     target_maps_set_ = true;
     200     2868979 :     nexus()->ExtractMaps(&target_maps_);
     201             :   }
     202             : 
     203             :   // Frame pointer for the frame that uses (calls) the IC.
     204             :   Address fp_;
     205             : 
     206             :   // All access to the program counter and constant pool of an IC structure is
     207             :   // indirect to make the code GC safe. This feature is crucial since
     208             :   // GetProperty and SetProperty are called and they in turn might
     209             :   // invoke the garbage collector.
     210             :   Address* pc_address_;
     211             : 
     212             :   // The constant pool of the code which originally called the IC (which might
     213             :   // be for the breakpointed copy of the original code).
     214             :   Address* constant_pool_address_;
     215             : 
     216             :   Isolate* isolate_;
     217             : 
     218             :   bool vector_set_;
     219             :   State old_state_;  // For saving if we marked as prototype failure.
     220             :   State state_;
     221             :   FeedbackSlotKind kind_;
     222             :   Handle<Map> receiver_map_;
     223             :   MaybeHandle<Object> maybe_handler_;
     224             : 
     225             :   ExtraICState extra_ic_state_;
     226             :   MapHandleList target_maps_;
     227             :   bool target_maps_set_;
     228             : 
     229             :   const char* slow_stub_reason_;
     230             : 
     231             :   FeedbackNexus* nexus_;
     232             : 
     233             :   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
     234             : };
     235             : 
     236             : 
     237           0 : class CallIC : public IC {
     238             :  public:
     239             :   CallIC(Isolate* isolate, CallICNexus* nexus)
     240             :       : IC(EXTRA_CALL_FRAME, isolate, nexus) {
     241             :     DCHECK(nexus != NULL);
     242             :   }
     243             : };
     244             : 
     245             : 
     246    11517888 : class LoadIC : public IC {
     247             :  public:
     248     4359620 :   LoadIC(Isolate* isolate, FeedbackNexus* nexus)
     249     7158268 :       : IC(NO_EXTRA_FRAME, isolate, nexus) {
     250             :     DCHECK(nexus != NULL);
     251             :     DCHECK(IsAnyLoad());
     252     4359622 :   }
     253             : 
     254        7510 :   static bool ShouldThrowReferenceError(FeedbackSlotKind kind) {
     255        7510 :     return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
     256             :   }
     257             : 
     258             :   bool ShouldThrowReferenceError() const {
     259      728067 :     return ShouldThrowReferenceError(kind());
     260             :   }
     261             : 
     262             :   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     263             :                                            Handle<Name> name);
     264             : 
     265             :  protected:
     266        5853 :   virtual Handle<Code> slow_stub() const {
     267        5853 :     return isolate()->builtins()->LoadIC_Slow();
     268             :   }
     269             : 
     270             :   // Update the inline cache and the global stub cache based on the
     271             :   // lookup result.
     272             :   void UpdateCaches(LookupIterator* lookup);
     273             : 
     274             :   Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) override;
     275             : 
     276             :   Handle<Code> CompileHandler(LookupIterator* lookup) override;
     277             : 
     278             :  private:
     279             :   // Creates a data handler that represents a load of a field by given index.
     280             :   static Handle<Smi> SimpleFieldLoad(Isolate* isolate, FieldIndex index);
     281             : 
     282             :   // Creates a data handler that represents a prototype chain check followed
     283             :   // by given Smi-handler that encoded a load from the holder.
     284             :   // Can be used only if GetPrototypeCheckCount() returns non negative value.
     285             :   Handle<Object> LoadFromPrototype(Handle<Map> receiver_map,
     286             :                                    Handle<JSObject> holder, Handle<Name> name,
     287             :                                    Handle<Smi> smi_handler);
     288             : 
     289             :   // Creates a data handler that represents a load of a non-existent property.
     290             :   // {holder} is the object from which the property is loaded. If no holder is
     291             :   // needed (e.g., for "nonexistent"), null_value() may be passed in.
     292             :   Handle<Object> LoadFullChain(Handle<Map> receiver_map, Handle<Object> holder,
     293             :                                Handle<Name> name, Handle<Smi> smi_handler);
     294             : 
     295             :   friend class IC;
     296             :   friend class NamedLoadHandlerCompiler;
     297             : };
     298             : 
     299     4189159 : class LoadGlobalIC : public LoadIC {
     300             :  public:
     301     2094580 :   LoadGlobalIC(Isolate* isolate, FeedbackNexus* nexus)
     302     2094580 :       : LoadIC(isolate, nexus) {}
     303             : 
     304             :   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Name> name);
     305             : 
     306             :  protected:
     307         665 :   Handle<Code> slow_stub() const override {
     308         665 :     return isolate()->builtins()->LoadGlobalIC_Slow();
     309             :   }
     310             : };
     311             : 
     312     1408136 : class KeyedLoadIC : public LoadIC {
     313             :  public:
     314      704068 :   KeyedLoadIC(Isolate* isolate, KeyedLoadICNexus* nexus)
     315      704068 :       : LoadIC(isolate, nexus) {
     316             :     DCHECK(nexus != NULL);
     317      704068 :   }
     318             : 
     319             :   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     320             :                                            Handle<Object> key);
     321             : 
     322             :  protected:
     323             :   // receiver is HeapObject because it could be a String or a JSObject
     324             :   void UpdateLoadElement(Handle<HeapObject> receiver);
     325             : 
     326             :  private:
     327             :   friend class IC;
     328             : 
     329             :   Handle<Object> LoadElementHandler(Handle<Map> receiver_map);
     330             : 
     331             :   void LoadElementPolymorphicHandlers(MapHandleList* receiver_maps,
     332             :                                       List<Handle<Object>>* handlers);
     333             : };
     334             : 
     335             : 
     336    10803464 : class StoreIC : public IC {
     337             :  public:
     338     4204991 :   StoreIC(Isolate* isolate, FeedbackNexus* nexus)
     339     6598471 :       : IC(NO_EXTRA_FRAME, isolate, nexus) {
     340             :     DCHECK(IsAnyStore());
     341     4204991 :   }
     342             : 
     343     6618627 :   LanguageMode language_mode() const {
     344    13237254 :     return nexus()->vector()->GetLanguageMode(nexus()->slot());
     345             :   }
     346             : 
     347             :   MUST_USE_RESULT MaybeHandle<Object> Store(
     348             :       Handle<Object> object, Handle<Name> name, Handle<Object> value,
     349             :       JSReceiver::StoreFromKeyed store_mode =
     350             :           JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
     351             : 
     352             :   bool LookupForWrite(LookupIterator* it, Handle<Object> value,
     353             :                       JSReceiver::StoreFromKeyed store_mode);
     354             : 
     355             :  protected:
     356             :   // Stub accessors.
     357             :   Handle<Code> slow_stub() const {
     358             :     // All StoreICs share the same slow stub.
     359      202480 :     return isolate()->builtins()->KeyedStoreIC_Slow();
     360             :   }
     361             : 
     362             :   // Update the inline cache and the global stub cache based on the
     363             :   // lookup result.
     364             :   void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
     365             :                     JSReceiver::StoreFromKeyed store_mode);
     366             :   Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) override;
     367             :   Handle<Code> CompileHandler(LookupIterator* lookup) override;
     368             : 
     369             :  private:
     370             :   Handle<Object> StoreTransition(Handle<Map> receiver_map,
     371             :                                  Handle<JSObject> holder,
     372             :                                  Handle<Map> transition, Handle<Name> name);
     373             : 
     374             :   friend class IC;
     375             : };
     376             : 
     377     3381884 : class StoreGlobalIC : public StoreIC {
     378             :  public:
     379     1690942 :   StoreGlobalIC(Isolate* isolate, FeedbackNexus* nexus)
     380     1690942 :       : StoreIC(isolate, nexus) {}
     381             : 
     382             :   MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
     383             :                                             Handle<Name> name,
     384             :                                             Handle<Object> value);
     385             : };
     386             : 
     387             : enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
     388             : 
     389             : 
     390             : enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
     391             : 
     392             : 
     393     1405076 : class KeyedStoreIC : public StoreIC {
     394             :  public:
     395             :   KeyedAccessStoreMode GetKeyedAccessStoreMode() {
     396       32433 :     return casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
     397             :   }
     398             : 
     399      702538 :   KeyedStoreIC(Isolate* isolate, KeyedStoreICNexus* nexus)
     400      702538 :       : StoreIC(isolate, nexus) {}
     401             : 
     402             :   MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
     403             :                                             Handle<Object> name,
     404             :                                             Handle<Object> value);
     405             : 
     406             :  protected:
     407             :   void UpdateStoreElement(Handle<Map> receiver_map,
     408             :                           KeyedAccessStoreMode store_mode);
     409             : 
     410             :  private:
     411             :   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
     412             :                                      KeyedAccessStoreMode store_mode);
     413             : 
     414             :   Handle<Object> StoreElementHandler(Handle<Map> receiver_map,
     415             :                                      KeyedAccessStoreMode store_mode);
     416             : 
     417             :   void StoreElementPolymorphicHandlers(MapHandleList* receiver_maps,
     418             :                                        List<Handle<Object>>* handlers,
     419             :                                        KeyedAccessStoreMode store_mode);
     420             : 
     421             :   friend class IC;
     422             : };
     423             : 
     424             : 
     425             : // Type Recording BinaryOpIC, that records the types of the inputs and outputs.
     426      875616 : class BinaryOpIC : public IC {
     427             :  public:
     428      437808 :   explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
     429             : 
     430             :   MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site,
     431             :                                  Handle<Object> left,
     432             :                                  Handle<Object> right) WARN_UNUSED_RESULT;
     433             : };
     434             : 
     435             : 
     436      545824 : class CompareIC : public IC {
     437             :  public:
     438      272912 :   CompareIC(Isolate* isolate, Token::Value op)
     439      272912 :       : IC(EXTRA_CALL_FRAME, isolate), op_(op) {}
     440             : 
     441             :   // Update the inline cache for the given operands.
     442             :   Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
     443             : 
     444             :   // Helper function for computing the condition for a compare operation.
     445             :   static Condition ComputeCondition(Token::Value op);
     446             : 
     447             :  private:
     448             :   static bool HasInlinedSmiCode(Address address);
     449             : 
     450             :   bool strict() const { return op_ == Token::EQ_STRICT; }
     451             :   Condition GetCondition() const { return ComputeCondition(op_); }
     452             : 
     453             :   static Code* GetRawUninitialized(Isolate* isolate, Token::Value op);
     454             : 
     455             :   static void Clear(Isolate* isolate, Address address, Code* target,
     456             :                     Address constant_pool);
     457             : 
     458             :   Token::Value op_;
     459             : 
     460             :   friend class IC;
     461             : };
     462             : 
     463             : 
     464      261386 : class ToBooleanIC : public IC {
     465             :  public:
     466      130693 :   explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
     467             : 
     468             :   Handle<Object> ToBoolean(Handle<Object> object);
     469             : };
     470             : 
     471             : 
     472             : // Helper for BinaryOpIC and CompareIC.
     473             : enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
     474             : void PatchInlinedSmiCode(Isolate* isolate, Address address,
     475             :                          InlinedSmiCheck check);
     476             : 
     477             : }  // namespace internal
     478             : }  // namespace v8
     479             : 
     480             : #endif  // V8_IC_H_

Generated by: LCOV version 1.10