LCOV - code coverage report
Current view: top level - src/ic - ic.h (source / functions) Hit Total Coverage
Test: app.info Lines: 55 56 98.2 %
Date: 2019-04-17 Functions: 22 31 71.0 %

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

Generated by: LCOV version 1.10