LCOV - code coverage report
Current view: top level - src/ic - ic.h (source / functions) Hit Total Coverage
Test: app.info Lines: 58 59 98.3 %
Date: 2019-01-20 Functions: 23 32 71.9 %

          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_IC_H_
       6             : #define V8_IC_IC_H_
       7             : 
       8             : #include <vector>
       9             : 
      10             : #include "src/feedback-vector.h"
      11             : #include "src/heap/factory.h"
      12             : #include "src/ic/stub-cache.h"
      13             : #include "src/isolate.h"
      14             : #include "src/message-template.h"
      15             : #include "src/objects/map.h"
      16             : #include "src/objects/maybe-object.h"
      17             : #include "src/objects/smi.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : enum class NamedPropertyType : bool { kNotOwn, kOwn };
      23             : 
      24             : //
      25             : // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
      26             : //
      27             : class IC {
      28             :  public:
      29             :   // Alias the inline cache state type to make the IC code more readable.
      30             :   typedef InlineCacheState State;
      31             : 
      32             :   static constexpr int kMaxKeyedPolymorphism = 4;
      33             : 
      34             :   // A polymorphic IC can handle at most 4 distinct maps before transitioning
      35             :   // to megamorphic state.
      36             :   static constexpr int kMaxPolymorphicMapCount = 4;
      37             : 
      38             :   // Construct the IC structure with the given number of extra
      39             :   // JavaScript frames on the stack.
      40             :   IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
      41             :      FeedbackSlotKind kind);
      42     6853648 :   virtual ~IC() = default;
      43             : 
      44             :   State state() const { return state_; }
      45             :   inline Address address() const;
      46             : 
      47             :   // Compute the current IC state based on the target stub, receiver and name.
      48             :   void UpdateState(Handle<Object> receiver, Handle<Object> name);
      49             : 
      50             :   bool RecomputeHandlerForName(Handle<Object> name);
      51             :   void MarkRecomputeHandler(Handle<Object> name) {
      52             :     DCHECK(RecomputeHandlerForName(name));
      53       56655 :     old_state_ = state_;
      54       56655 :     state_ = RECOMPUTE_HANDLER;
      55             :   }
      56             : 
      57      705759 :   bool IsAnyLoad() const {
      58     1129976 :     return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
      59             :   }
      60             :   bool IsAnyStore() const {
      61             :     return IsStoreIC() || IsStoreOwnIC() || IsStoreGlobalIC() ||
      62             :            IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind());
      63             :   }
      64             : 
      65             :   static inline bool IsHandler(MaybeObject object);
      66             : 
      67             :   // Nofity the IC system that a feedback has changed.
      68             :   static void OnFeedbackChanged(Isolate* isolate, FeedbackVector vector,
      69             :                                 FeedbackSlot slot, JSFunction host_function,
      70             :                                 const char* reason);
      71             : 
      72             :   static void OnFeedbackChanged(Isolate* isolate, FeedbackNexus* nexus,
      73             :                                 JSFunction host_function, const char* reason);
      74             : 
      75             :  protected:
      76             :   Address fp() const { return fp_; }
      77           0 :   Address pc() const { return *pc_address_; }
      78             : 
      79       39552 :   void set_slow_stub_reason(const char* reason) { slow_stub_reason_ = reason; }
      80             : 
      81             :   Isolate* isolate() const { return isolate_; }
      82             : 
      83             :   // Get the caller function object.
      84             :   JSFunction GetHostFunction() const;
      85             : 
      86             :   inline bool AddressIsDeoptimizedCode() const;
      87             :   inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
      88             :                                               Address address);
      89             : 
      90             :   bool is_vector_set() { return vector_set_; }
      91             :   inline bool vector_needs_update();
      92             : 
      93             :   // Configure for most states.
      94             :   bool ConfigureVectorState(IC::State new_state, Handle<Object> key);
      95             :   // Configure the vector for PREMONOMORPHIC.
      96             :   void ConfigureVectorState(Handle<Map> map);
      97             :   // Configure the vector for MONOMORPHIC.
      98             :   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
      99             :                             Handle<Object> handler);
     100             :   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
     101             :                             const MaybeObjectHandle& handler);
     102             :   // Configure the vector for POLYMORPHIC.
     103             :   void ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
     104             :                             MaybeObjectHandles* handlers);
     105             : 
     106             :   char TransitionMarkFromState(IC::State state);
     107             :   void TraceIC(const char* type, Handle<Object> name);
     108             :   void TraceIC(const char* type, Handle<Object> name, State old_state,
     109             :                State new_state);
     110             : 
     111             :   MaybeHandle<Object> TypeError(MessageTemplate, Handle<Object> object,
     112             :                                 Handle<Object> key);
     113             :   MaybeHandle<Object> ReferenceError(Handle<Name> name);
     114             : 
     115             :   void TraceHandlerCacheHitStats(LookupIterator* lookup);
     116             : 
     117             :   void UpdateMonomorphicIC(const MaybeObjectHandle& handler, Handle<Name> name);
     118             :   bool UpdatePolymorphicIC(Handle<Name> name, const MaybeObjectHandle& handler);
     119             :   void UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
     120             :                               const MaybeObjectHandle& handler);
     121             : 
     122             :   StubCache* stub_cache();
     123             : 
     124             :   void CopyICToMegamorphicCache(Handle<Name> name);
     125             :   bool IsTransitionOfMonomorphicTarget(Map source_map, Map target_map);
     126             :   void PatchCache(Handle<Name> name, Handle<Object> handler);
     127             :   void PatchCache(Handle<Name> name, const MaybeObjectHandle& handler);
     128             :   FeedbackSlotKind kind() const { return kind_; }
     129     6695779 :   bool IsGlobalIC() const { return IsLoadGlobalIC() || IsStoreGlobalIC(); }
     130             :   bool IsLoadIC() const { return IsLoadICKind(kind_); }
     131             :   bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
     132             :   bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
     133             :   bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); }
     134             :   bool IsStoreIC() const { return IsStoreICKind(kind_); }
     135             :   bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); }
     136             :   bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
     137     1220073 :   bool is_keyed() const {
     138     5403789 :     return IsKeyedLoadIC() || IsKeyedStoreIC() ||
     139             :            IsStoreInArrayLiteralICKind(kind_);
     140             :   }
     141             :   bool ShouldRecomputeHandler(Handle<String> name);
     142             : 
     143             :   Handle<Map> receiver_map() { return receiver_map_; }
     144             :   inline void update_receiver_map(Handle<Object> receiver);
     145             : 
     146      719557 :   void TargetMaps(MapHandles* list) {
     147             :     FindTargetMaps();
     148     1942538 :     for (Handle<Map> map : target_maps_) {
     149      503412 :       list->push_back(map);
     150             :     }
     151      719565 :   }
     152             : 
     153      329278 :   Map FirstTargetMap() {
     154             :     FindTargetMaps();
     155      887145 :     return !target_maps_.empty() ? *target_maps_[0] : Map();
     156             :   }
     157             : 
     158             :   State saved_state() const {
     159             :     return state() == RECOMPUTE_HANDLER ? old_state_ : state();
     160             :   }
     161             : 
     162             :   const FeedbackNexus* nexus() const { return &nexus_; }
     163             :   FeedbackNexus* nexus() { return &nexus_; }
     164             : 
     165             :  private:
     166             :   inline Address constant_pool() const;
     167             :   inline Address raw_constant_pool() const;
     168             : 
     169             :   void FindTargetMaps() {
     170     1048835 :     if (target_maps_set_) return;
     171      706844 :     target_maps_set_ = true;
     172      706844 :     nexus()->ExtractMaps(&target_maps_);
     173             :   }
     174             : 
     175             :   // Frame pointer for the frame that uses (calls) the IC.
     176             :   Address fp_;
     177             : 
     178             :   // All access to the program counter and constant pool of an IC structure is
     179             :   // indirect to make the code GC safe. This feature is crucial since
     180             :   // GetProperty and SetProperty are called and they in turn might
     181             :   // invoke the garbage collector.
     182             :   Address* pc_address_;
     183             : 
     184             :   // The constant pool of the code which originally called the IC (which might
     185             :   // be for the breakpointed copy of the original code).
     186             :   Address* constant_pool_address_;
     187             : 
     188             :   Isolate* isolate_;
     189             : 
     190             :   bool vector_set_;
     191             :   State old_state_;  // For saving if we marked as prototype failure.
     192             :   State state_;
     193             :   FeedbackSlotKind kind_;
     194             :   Handle<Map> receiver_map_;
     195             :   MaybeObjectHandle maybe_handler_;
     196             : 
     197             :   MapHandles target_maps_;
     198             :   bool target_maps_set_;
     199             : 
     200             :   const char* slow_stub_reason_;
     201             : 
     202             :   FeedbackNexus nexus_;
     203             : 
     204             :   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
     205             : };
     206             : 
     207             : 
     208     4871886 : class LoadIC : public IC {
     209             :  public:
     210     1291948 :   LoadIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
     211             :          FeedbackSlotKind kind)
     212     3579899 :       : IC(isolate, vector, slot, kind) {
     213             :     DCHECK(IsAnyLoad());
     214     1291954 :   }
     215             : 
     216        6437 :   static bool ShouldThrowReferenceError(FeedbackSlotKind kind) {
     217        6437 :     return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
     218             :   }
     219             : 
     220             :   bool ShouldThrowReferenceError() const {
     221      325837 :     return ShouldThrowReferenceError(kind());
     222             :   }
     223             : 
     224             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     225             :                                                  Handle<Name> name);
     226             : 
     227             :  protected:
     228        1385 :   virtual Handle<Code> slow_stub() const {
     229        1385 :     return BUILTIN_CODE(isolate(), LoadIC_Slow);
     230             :   }
     231             : 
     232             :   // Update the inline cache and the global stub cache based on the
     233             :   // lookup result.
     234             :   void UpdateCaches(LookupIterator* lookup);
     235             : 
     236             :  private:
     237             :   Handle<Object> ComputeHandler(LookupIterator* lookup);
     238             : 
     239             :   friend class IC;
     240             :   friend class NamedLoadHandlerCompiler;
     241             : };
     242             : 
     243     4145734 : class LoadGlobalIC : public LoadIC {
     244             :  public:
     245     2072861 :   LoadGlobalIC(Isolate* isolate, Handle<FeedbackVector> vector,
     246             :                FeedbackSlot slot, FeedbackSlotKind kind)
     247     2072862 :       : LoadIC(isolate, vector, slot, kind) {}
     248             : 
     249             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Name> name);
     250             : 
     251             :  protected:
     252         550 :   Handle<Code> slow_stub() const override {
     253         550 :     return BUILTIN_CODE(isolate(), LoadGlobalIC_Slow);
     254             :   }
     255             : };
     256             : 
     257      430180 : class KeyedLoadIC : public LoadIC {
     258             :  public:
     259      215090 :   KeyedLoadIC(Isolate* isolate, Handle<FeedbackVector> vector,
     260             :               FeedbackSlot slot, FeedbackSlotKind kind)
     261      215089 :       : LoadIC(isolate, vector, slot, kind) {}
     262             : 
     263             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     264             :                                                  Handle<Object> key);
     265             : 
     266             :  protected:
     267             :   // receiver is HeapObject because it could be a String or a JSObject
     268             :   void UpdateLoadElement(Handle<HeapObject> receiver,
     269             :                          KeyedAccessLoadMode load_mode);
     270             : 
     271             :  private:
     272             :   friend class IC;
     273             : 
     274             :   Handle<Object> LoadElementHandler(Handle<Map> receiver_map,
     275             :                                     KeyedAccessLoadMode load_mode);
     276             : 
     277             :   void LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
     278             :                                       MaybeObjectHandles* handlers,
     279             :                                       KeyedAccessLoadMode load_mode);
     280             : 
     281             :   // Returns true if the receiver_map has a kElement or kIndexedString
     282             :   // handler in the nexus currently but didn't yet allow out of bounds
     283             :   // accesses.
     284             :   bool CanChangeToAllowOutOfBounds(Handle<Map> receiver_map);
     285             : };
     286             : 
     287             : 
     288     4569916 : class StoreIC : public IC {
     289             :  public:
     290     1296189 :   StoreIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
     291             :           FeedbackSlotKind kind, LanguageMode language_mode)
     292     3273726 :       : IC(isolate, vector, slot, kind), language_mode_(language_mode) {
     293             :     DCHECK(IsAnyStore());
     294     1296191 :   }
     295             : 
     296             :   LanguageMode language_mode() const { return language_mode_; }
     297             : 
     298             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(
     299             :       Handle<Object> object, Handle<Name> name, Handle<Object> value,
     300             :       StoreOrigin store_origin = StoreOrigin::kNamed);
     301             : 
     302             :   bool LookupForWrite(LookupIterator* it, Handle<Object> value,
     303             :                       StoreOrigin store_origin);
     304             : 
     305             :  protected:
     306             :   // Stub accessors.
     307       27285 :   virtual Handle<Code> slow_stub() const {
     308             :     // All StoreICs share the same slow stub.
     309       27285 :     return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
     310             :   }
     311             : 
     312             :   // Update the inline cache and the global stub cache based on the
     313             :   // lookup result.
     314             :   void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
     315             :                     StoreOrigin store_origin);
     316             : 
     317             :   // TODO(v8:8580): Instead of storing the language mode, compute it lazily
     318             :   // from the closure and context when needed. We only need it when throwing
     319             :   // exceptions, so it is OK to be slow.
     320             :   LanguageMode language_mode_;
     321             : 
     322             :  private:
     323             :   MaybeObjectHandle ComputeHandler(LookupIterator* lookup);
     324             : 
     325             :   friend class IC;
     326             : };
     327             : 
     328     3291840 : class StoreGlobalIC : public StoreIC {
     329             :  public:
     330     1645920 :   StoreGlobalIC(Isolate* isolate, Handle<FeedbackVector> vector,
     331             :                 FeedbackSlot slot, FeedbackSlotKind kind,
     332             :                 LanguageMode language_mode)
     333     1645920 :       : StoreIC(isolate, vector, slot, kind, language_mode) {}
     334             : 
     335             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Name> name,
     336             :                                                   Handle<Object> value);
     337             : 
     338             :  protected:
     339         658 :   Handle<Code> slow_stub() const override {
     340         658 :     return BUILTIN_CODE(isolate(), StoreGlobalIC_Slow);
     341             :   }
     342             : };
     343             : 
     344             : enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
     345             : 
     346             : 
     347             : enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
     348             : 
     349             : 
     350      492281 : class KeyedStoreIC : public StoreIC {
     351             :  public:
     352             :   KeyedAccessStoreMode GetKeyedAccessStoreMode() {
     353       11853 :     return nexus()->GetKeyedAccessStoreMode();
     354             :   }
     355             : 
     356      160665 :   KeyedStoreIC(Isolate* isolate, Handle<FeedbackVector> vector,
     357             :                FeedbackSlot slot, FeedbackSlotKind kind,
     358             :                LanguageMode language_mode)
     359      331615 :       : StoreIC(isolate, vector, slot, kind, language_mode) {}
     360             : 
     361             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Object> object,
     362             :                                                   Handle<Object> name,
     363             :                                                   Handle<Object> value);
     364             : 
     365             :  protected:
     366             :   void UpdateStoreElement(Handle<Map> receiver_map,
     367             :                           KeyedAccessStoreMode store_mode,
     368             :                           bool receiver_was_cow);
     369             : 
     370         484 :   Handle<Code> slow_stub() const override {
     371         484 :     return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
     372             :   }
     373             : 
     374             :  private:
     375             :   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
     376             :                                      KeyedAccessStoreMode store_mode);
     377             : 
     378             :   Handle<Object> StoreElementHandler(Handle<Map> receiver_map,
     379             :                                      KeyedAccessStoreMode store_mode);
     380             : 
     381             :   void StoreElementPolymorphicHandlers(MapHandles* receiver_maps,
     382             :                                        MaybeObjectHandles* handlers,
     383             :                                        KeyedAccessStoreMode store_mode);
     384             : 
     385             :   friend class IC;
     386             : };
     387             : 
     388      341902 : class StoreInArrayLiteralIC : public KeyedStoreIC {
     389             :  public:
     390      170952 :   StoreInArrayLiteralIC(Isolate* isolate, Handle<FeedbackVector> vector,
     391             :                         FeedbackSlot slot)
     392             :       : KeyedStoreIC(isolate, vector, slot,
     393             :                      FeedbackSlotKind::kStoreInArrayLiteral,
     394      170950 :                      LanguageMode::kStrict) {
     395             :     DCHECK(IsStoreInArrayLiteralICKind(kind()));
     396      170950 :   }
     397             : 
     398             :   void Store(Handle<JSArray> array, Handle<Object> index, Handle<Object> value);
     399             : 
     400             :  private:
     401          36 :   Handle<Code> slow_stub() const override {
     402          36 :     return BUILTIN_CODE(isolate(), StoreInArrayLiteralIC_Slow);
     403             :   }
     404             : };
     405             : 
     406             : }  // namespace internal
     407             : }  // namespace v8
     408             : 
     409             : #endif  // V8_IC_IC_H_

Generated by: LCOV version 1.10