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-02-19 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             :   // Construct the IC structure with the given number of extra
      35             :   // JavaScript frames on the stack.
      36             :   IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
      37             :      FeedbackSlotKind kind);
      38     7383676 :   virtual ~IC() = default;
      39             : 
      40             :   State state() const { return state_; }
      41             :   inline Address address() const;
      42             : 
      43             :   // Compute the current IC state based on the target stub, receiver and name.
      44             :   void UpdateState(Handle<Object> receiver, Handle<Object> name);
      45             : 
      46             :   bool RecomputeHandlerForName(Handle<Object> name);
      47             :   void MarkRecomputeHandler(Handle<Object> name) {
      48             :     DCHECK(RecomputeHandlerForName(name));
      49       53537 :     old_state_ = state_;
      50       53537 :     state_ = RECOMPUTE_HANDLER;
      51             :   }
      52             : 
      53      701300 :   bool IsAnyLoad() const {
      54     1123019 :     return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
      55             :   }
      56             :   bool IsAnyStore() const {
      57             :     return IsStoreIC() || IsStoreOwnIC() || IsStoreGlobalIC() ||
      58             :            IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind());
      59             :   }
      60             : 
      61             :   static inline bool IsHandler(MaybeObject object);
      62             : 
      63             :   // Nofity the IC system that a feedback has changed.
      64             :   static void OnFeedbackChanged(Isolate* isolate, FeedbackVector vector,
      65             :                                 FeedbackSlot slot, JSFunction host_function,
      66             :                                 const char* reason);
      67             : 
      68             :   static void OnFeedbackChanged(Isolate* isolate, FeedbackNexus* nexus,
      69             :                                 JSFunction host_function, const char* reason);
      70             : 
      71             :  protected:
      72             :   Address fp() const { return fp_; }
      73           0 :   Address pc() const { return *pc_address_; }
      74             : 
      75       38543 :   void set_slow_stub_reason(const char* reason) { slow_stub_reason_ = reason; }
      76             : 
      77             :   Isolate* isolate() const { return isolate_; }
      78             : 
      79             :   // Get the caller function object.
      80             :   JSFunction GetHostFunction() const;
      81             : 
      82             :   inline bool AddressIsDeoptimizedCode() const;
      83             :   inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
      84             :                                               Address address);
      85             : 
      86             :   bool is_vector_set() { return vector_set_; }
      87             :   inline bool vector_needs_update();
      88             : 
      89             :   // Configure for most states.
      90             :   bool ConfigureVectorState(IC::State new_state, Handle<Object> key);
      91             :   // Configure the vector for PREMONOMORPHIC.
      92             :   void ConfigureVectorState(Handle<Map> map);
      93             :   // Configure the vector for MONOMORPHIC.
      94             :   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
      95             :                             Handle<Object> handler);
      96             :   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
      97             :                             const MaybeObjectHandle& handler);
      98             :   // Configure the vector for POLYMORPHIC.
      99             :   void ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
     100             :                             MaybeObjectHandles* 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, Handle<Object> object,
     108             :                                 Handle<Object> key);
     109             :   MaybeHandle<Object> ReferenceError(Handle<Name> name);
     110             : 
     111             :   void TraceHandlerCacheHitStats(LookupIterator* lookup);
     112             : 
     113             :   void UpdateMonomorphicIC(const MaybeObjectHandle& handler, Handle<Name> name);
     114             :   bool UpdatePolymorphicIC(Handle<Name> name, const MaybeObjectHandle& handler);
     115             :   void UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
     116             :                               const MaybeObjectHandle& handler);
     117             : 
     118             :   StubCache* stub_cache();
     119             : 
     120             :   void CopyICToMegamorphicCache(Handle<Name> name);
     121             :   bool IsTransitionOfMonomorphicTarget(Map source_map, Map target_map);
     122             :   void PatchCache(Handle<Name> name, Handle<Object> handler);
     123             :   void PatchCache(Handle<Name> name, const MaybeObjectHandle& handler);
     124             :   FeedbackSlotKind kind() const { return kind_; }
     125     7347321 :   bool IsGlobalIC() const { return IsLoadGlobalIC() || IsStoreGlobalIC(); }
     126             :   bool IsLoadIC() const { return IsLoadICKind(kind_); }
     127             :   bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
     128             :   bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
     129             :   bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); }
     130             :   bool IsStoreIC() const { return IsStoreICKind(kind_); }
     131             :   bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); }
     132             :   bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
     133     1194441 :   bool is_keyed() const {
     134     5820859 :     return IsKeyedLoadIC() || IsKeyedStoreIC() ||
     135             :            IsStoreInArrayLiteralICKind(kind_);
     136             :   }
     137             :   bool ShouldRecomputeHandler(Handle<String> name);
     138             : 
     139             :   Handle<Map> receiver_map() { return receiver_map_; }
     140             :   inline void update_receiver_map(Handle<Object> receiver);
     141             : 
     142      701432 :   void TargetMaps(MapHandles* list) {
     143             :     FindTargetMaps();
     144     1897760 :     for (Handle<Map> map : target_maps_) {
     145      494886 :       list->push_back(map);
     146             :     }
     147      701438 :   }
     148             : 
     149      321674 :   Map FirstTargetMap() {
     150             :     FindTargetMaps();
     151      866182 :     return !target_maps_.empty() ? *target_maps_[0] : Map();
     152             :   }
     153             : 
     154             :   State saved_state() const {
     155             :     return state() == RECOMPUTE_HANDLER ? old_state_ : state();
     156             :   }
     157             : 
     158             :   const FeedbackNexus* nexus() const { return &nexus_; }
     159             :   FeedbackNexus* nexus() { return &nexus_; }
     160             : 
     161             :  private:
     162             :   inline Address constant_pool() const;
     163             :   inline Address raw_constant_pool() const;
     164             : 
     165             :   void FindTargetMaps() {
     166     1023106 :     if (target_maps_set_) return;
     167      688855 :     target_maps_set_ = true;
     168      688855 :     nexus()->ExtractMaps(&target_maps_);
     169             :   }
     170             : 
     171             :   // Frame pointer for the frame that uses (calls) the IC.
     172             :   Address fp_;
     173             : 
     174             :   // All access to the program counter and constant pool of an IC structure is
     175             :   // indirect to make the code GC safe. This feature is crucial since
     176             :   // GetProperty and SetProperty are called and they in turn might
     177             :   // invoke the garbage collector.
     178             :   Address* pc_address_;
     179             : 
     180             :   // The constant pool of the code which originally called the IC (which might
     181             :   // be for the breakpointed copy of the original code).
     182             :   Address* constant_pool_address_;
     183             : 
     184             :   Isolate* isolate_;
     185             : 
     186             :   bool vector_set_;
     187             :   State old_state_;  // For saving if we marked as prototype failure.
     188             :   State state_;
     189             :   FeedbackSlotKind kind_;
     190             :   Handle<Map> receiver_map_;
     191             :   MaybeObjectHandle maybe_handler_;
     192             : 
     193             :   MapHandles target_maps_;
     194             :   bool target_maps_set_;
     195             : 
     196             :   const char* slow_stub_reason_;
     197             : 
     198             :   FeedbackNexus nexus_;
     199             : 
     200             :   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
     201             : };
     202             : 
     203             : 
     204     5014135 : class LoadIC : public IC {
     205             :  public:
     206     1274414 :   LoadIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
     207             :          FeedbackSlotKind kind)
     208     3739663 :       : IC(isolate, vector, slot, kind) {
     209             :     DCHECK(IsAnyLoad());
     210     1274422 :   }
     211             : 
     212        6437 :   static bool ShouldThrowReferenceError(FeedbackSlotKind kind) {
     213        6437 :     return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
     214             :   }
     215             : 
     216             :   bool ShouldThrowReferenceError() const {
     217      323539 :     return ShouldThrowReferenceError(kind());
     218             :   }
     219             : 
     220             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     221             :                                                  Handle<Name> name);
     222             : 
     223             :  protected:
     224        1364 :   virtual Handle<Code> slow_stub() const {
     225        1364 :     return BUILTIN_CODE(isolate(), LoadIC_Slow);
     226             :   }
     227             : 
     228             :   // Update the inline cache and the global stub cache based on the
     229             :   // lookup result.
     230             :   void UpdateCaches(LookupIterator* lookup);
     231             : 
     232             :  private:
     233             :   Handle<Object> ComputeHandler(LookupIterator* lookup);
     234             : 
     235             :   friend class IC;
     236             :   friend class NamedLoadHandlerCompiler;
     237             : };
     238             : 
     239     4502410 : class LoadGlobalIC : public LoadIC {
     240             :  public:
     241     2251197 :   LoadGlobalIC(Isolate* isolate, Handle<FeedbackVector> vector,
     242             :                FeedbackSlot slot, FeedbackSlotKind kind)
     243     2251205 :       : LoadIC(isolate, vector, slot, kind) {}
     244             : 
     245             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Name> name);
     246             : 
     247             :  protected:
     248         550 :   Handle<Code> slow_stub() const override {
     249         550 :     return BUILTIN_CODE(isolate(), LoadGlobalIC_Slow);
     250             :   }
     251             : };
     252             : 
     253      428104 : class KeyedLoadIC : public LoadIC {
     254             :  public:
     255      214052 :   KeyedLoadIC(Isolate* isolate, Handle<FeedbackVector> vector,
     256             :               FeedbackSlot slot, FeedbackSlotKind kind)
     257      214052 :       : LoadIC(isolate, vector, slot, kind) {}
     258             : 
     259             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     260             :                                                  Handle<Object> key);
     261             : 
     262             :  protected:
     263             :   // receiver is HeapObject because it could be a String or a JSObject
     264             :   void UpdateLoadElement(Handle<HeapObject> receiver,
     265             :                          KeyedAccessLoadMode load_mode);
     266             : 
     267             :  private:
     268             :   friend class IC;
     269             : 
     270             :   Handle<Object> LoadElementHandler(Handle<Map> receiver_map,
     271             :                                     KeyedAccessLoadMode load_mode);
     272             : 
     273             :   void LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
     274             :                                       MaybeObjectHandles* handlers,
     275             :                                       KeyedAccessLoadMode load_mode);
     276             : 
     277             :   // Returns true if the receiver_map has a kElement or kIndexedString
     278             :   // handler in the nexus currently but didn't yet allow out of bounds
     279             :   // accesses.
     280             :   bool CanChangeToAllowOutOfBounds(Handle<Map> receiver_map);
     281             : };
     282             : 
     283             : 
     284     5280892 : class StoreIC : public IC {
     285             :  public:
     286     1636912 :   StoreIC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
     287             :           FeedbackSlotKind kind)
     288     3643980 :       : IC(isolate, vector, slot, kind) {
     289             :     DCHECK(IsAnyStore());
     290     1636912 :   }
     291             : 
     292             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(
     293             :       Handle<Object> object, Handle<Name> name, Handle<Object> value,
     294             :       StoreOrigin store_origin = StoreOrigin::kNamed);
     295             : 
     296             :   bool LookupForWrite(LookupIterator* it, Handle<Object> value,
     297             :                       StoreOrigin store_origin);
     298             : 
     299             :  protected:
     300             :   // Stub accessors.
     301       27241 :   virtual Handle<Code> slow_stub() const {
     302             :     // All StoreICs share the same slow stub.
     303       27241 :     return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
     304             :   }
     305             : 
     306             :   // Update the inline cache and the global stub cache based on the
     307             :   // lookup result.
     308             :   void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
     309             :                     StoreOrigin store_origin);
     310             : 
     311             :  private:
     312             :   MaybeObjectHandle ComputeHandler(LookupIterator* lookup);
     313             : 
     314             :   friend class IC;
     315             : };
     316             : 
     317     3371822 : class StoreGlobalIC : public StoreIC {
     318             :  public:
     319     1685911 :   StoreGlobalIC(Isolate* isolate, Handle<FeedbackVector> vector,
     320             :                 FeedbackSlot slot, FeedbackSlotKind kind)
     321     1685911 :       : StoreIC(isolate, vector, slot, kind) {}
     322             : 
     323             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Name> name,
     324             :                                                   Handle<Object> value);
     325             : 
     326             :  protected:
     327         652 :   Handle<Code> slow_stub() const override {
     328         652 :     return BUILTIN_CODE(isolate(), StoreGlobalIC_Slow);
     329             :   }
     330             : };
     331             : 
     332             : enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
     333             : 
     334             : 
     335             : enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
     336             : 
     337             : 
     338      480426 : class KeyedStoreIC : public StoreIC {
     339             :  public:
     340             :   KeyedAccessStoreMode GetKeyedAccessStoreMode() {
     341       11569 :     return nexus()->GetKeyedAccessStoreMode();
     342             :   }
     343             : 
     344      159269 :   KeyedStoreIC(Isolate* isolate, Handle<FeedbackVector> vector,
     345             :                FeedbackSlot slot, FeedbackSlotKind kind)
     346      321156 :       : StoreIC(isolate, vector, slot, kind) {}
     347             : 
     348             :   V8_WARN_UNUSED_RESULT MaybeHandle<Object> Store(Handle<Object> object,
     349             :                                                   Handle<Object> name,
     350             :                                                   Handle<Object> value);
     351             : 
     352             :  protected:
     353             :   void UpdateStoreElement(Handle<Map> receiver_map,
     354             :                           KeyedAccessStoreMode store_mode,
     355             :                           bool receiver_was_cow);
     356             : 
     357         484 :   Handle<Code> slow_stub() const override {
     358         484 :     return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
     359             :   }
     360             : 
     361             :  private:
     362             :   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
     363             :                                      KeyedAccessStoreMode store_mode);
     364             : 
     365             :   Handle<Object> StoreElementHandler(Handle<Map> receiver_map,
     366             :                                      KeyedAccessStoreMode store_mode);
     367             : 
     368             :   void StoreElementPolymorphicHandlers(MapHandles* receiver_maps,
     369             :                                        MaybeObjectHandles* handlers,
     370             :                                        KeyedAccessStoreMode store_mode);
     371             : 
     372             :   friend class IC;
     373             : };
     374             : 
     375      323776 : class StoreInArrayLiteralIC : public KeyedStoreIC {
     376             :  public:
     377      161888 :   StoreInArrayLiteralIC(Isolate* isolate, Handle<FeedbackVector> vector,
     378             :                         FeedbackSlot slot)
     379             :       : KeyedStoreIC(isolate, vector, slot,
     380      161887 :                      FeedbackSlotKind::kStoreInArrayLiteral) {
     381             :     DCHECK(IsStoreInArrayLiteralICKind(kind()));
     382      161887 :   }
     383             : 
     384             :   void Store(Handle<JSArray> array, Handle<Object> index, Handle<Object> value);
     385             : 
     386             :  private:
     387          36 :   Handle<Code> slow_stub() const override {
     388          36 :     return BUILTIN_CODE(isolate(), StoreInArrayLiteralIC_Slow);
     389             :   }
     390             : };
     391             : 
     392             : }  // namespace internal
     393             : }  // namespace v8
     394             : 
     395             : #endif  // V8_IC_IC_H_

Generated by: LCOV version 1.10