LCOV - code coverage report
Current view: top level - src/ic - ic.h (source / functions) Hit Total Coverage
Test: app.info Lines: 62 68 91.2 %
Date: 2017-10-20 Functions: 22 34 64.7 %

          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 <vector>
       9             : 
      10             : #include "src/factory.h"
      11             : #include "src/feedback-vector.h"
      12             : #include "src/macro-assembler.h"
      13             : #include "src/messages.h"
      14             : #include "src/objects/map.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19             : //
      20             : // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
      21             : //
      22             : class IC {
      23             :  public:
      24             :   // Alias the inline cache state type to make the IC code more readable.
      25             :   typedef InlineCacheState State;
      26             : 
      27             :   // The IC code is either invoked with no extra frames on the stack
      28             :   // or with a single extra frame for supporting calls.
      29             :   enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 };
      30             : 
      31             :   static constexpr int kMaxKeyedPolymorphism = 4;
      32             : 
      33             :   // A polymorphic IC can handle at most 4 distinct maps before transitioning
      34             :   // to megamorphic state.
      35             :   static constexpr int kMaxPolymorphicMapCount = 4;
      36             : 
      37             :   // Construct the IC structure with the given number of extra
      38             :   // JavaScript frames on the stack.
      39             :   IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = nullptr);
      40     8598330 :   virtual ~IC() {}
      41             : 
      42             :   State state() const { return state_; }
      43             :   inline Address address() const;
      44             : 
      45             :   // Compute the current IC state based on the target stub, receiver and name.
      46             :   void UpdateState(Handle<Object> receiver, Handle<Object> name);
      47             : 
      48             :   bool RecomputeHandlerForName(Handle<Object> name);
      49             :   void MarkRecomputeHandler(Handle<Object> name) {
      50             :     DCHECK(RecomputeHandlerForName(name));
      51       64034 :     old_state_ = state_;
      52       64034 :     state_ = RECOMPUTE_HANDLER;
      53             :   }
      54             : 
      55      858465 :   bool IsAnyLoad() const {
      56     1325956 :     return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
      57             :   }
      58             :   bool IsAnyStore() const {
      59             :     return IsStoreIC() || IsStoreOwnIC() || IsStoreGlobalIC() ||
      60             :            IsKeyedStoreIC();
      61             :   }
      62             : 
      63             :   static inline bool IsHandler(Object* object);
      64             : 
      65             :   // Nofity the IC system that a feedback has changed.
      66             :   static void OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
      67             :                                 JSFunction* host_function);
      68             : 
      69             :  protected:
      70             :   Address fp() const { return fp_; }
      71           0 :   Address pc() const { return *pc_address_; }
      72             : 
      73      181598 :   void set_slow_stub_reason(const char* reason) { slow_stub_reason_ = reason; }
      74             : 
      75             :   Address GetAbstractPC(int* line, int* column) const;
      76             :   Isolate* isolate() const { return isolate_; }
      77             : 
      78             :   // Get the caller function object.
      79             :   JSFunction* GetHostFunction() const;
      80             : 
      81             :   inline bool AddressIsDeoptimizedCode() const;
      82             :   inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
      83             :                                               Address address);
      84             : 
      85             :   bool is_vector_set() { return vector_set_; }
      86      566251 :   bool vector_needs_update() {
      87      545339 :     return (!vector_set_ &&
      88       20912 :             (state() != MEGAMORPHIC ||
      89      515491 :              Smi::ToInt(nexus()->GetFeedbackExtra()) != ELEMENT));
      90             :   }
      91             : 
      92             :   // Configure for most states.
      93             :   void ConfigureVectorState(IC::State new_state, Handle<Object> key);
      94             :   // Configure the vector for MONOMORPHIC.
      95             :   void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
      96             :                             Handle<Object> handler);
      97             :   // Configure the vector for POLYMORPHIC.
      98             :   void ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
      99             :                             ObjectHandles* handlers);
     100             : 
     101             :   char TransitionMarkFromState(IC::State state);
     102             :   void TraceIC(const char* type, Handle<Object> name);
     103             :   void TraceIC(const char* type, Handle<Object> name, State old_state,
     104             :                State new_state);
     105             : 
     106             :   MaybeHandle<Object> TypeError(MessageTemplate::Template,
     107             :                                 Handle<Object> object, Handle<Object> key);
     108             :   MaybeHandle<Object> ReferenceError(Handle<Name> name);
     109             : 
     110             :   void TraceHandlerCacheHitStats(LookupIterator* lookup);
     111             : 
     112             :   // Compute the handler either by compiling or by retrieving a cached version.
     113             :   Handle<Object> ComputeHandler(LookupIterator* lookup);
     114           0 :   virtual Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) {
     115           0 :     UNREACHABLE();
     116             :   }
     117           0 :   virtual Handle<Code> CompileHandler(LookupIterator* lookup) {
     118           0 :     UNREACHABLE();
     119             :   }
     120             : 
     121             :   void UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name);
     122             :   bool UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code);
     123             :   void UpdateMegamorphicCache(Map* map, Name* name, Object* code);
     124             : 
     125             :   StubCache* stub_cache();
     126             : 
     127             :   void CopyICToMegamorphicCache(Handle<Name> name);
     128             :   bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
     129             :   void PatchCache(Handle<Name> name, Handle<Object> code);
     130             :   FeedbackSlotKind kind() const { return kind_; }
     131             :   bool IsLoadIC() const { return IsLoadICKind(kind_); }
     132             :   bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
     133             :   bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
     134             :   bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); }
     135             :   bool IsStoreIC() const { return IsStoreICKind(kind_); }
     136             :   bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); }
     137             :   bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
     138     6780667 :   bool is_keyed() const { return IsKeyedLoadIC() || IsKeyedStoreIC(); }
     139             :   bool ShouldRecomputeHandler(Handle<String> name);
     140             : 
     141             :   Handle<Map> receiver_map() { return receiver_map_; }
     142    10430709 :   void update_receiver_map(Handle<Object> receiver) {
     143    10430709 :     if (receiver->IsSmi()) {
     144       39920 :       receiver_map_ = isolate_->factory()->heap_number_map();
     145             :     } else {
     146    10410750 :       receiver_map_ = handle(HeapObject::cast(*receiver)->map());
     147             :     }
     148    10430710 :   }
     149             : 
     150      894204 :   void TargetMaps(MapHandles* list) {
     151             :     FindTargetMaps();
     152     2516154 :     for (Handle<Map> map : target_maps_) {
     153      727746 :       list->push_back(map);
     154             :     }
     155      894204 :   }
     156             : 
     157      571355 :   Map* FirstTargetMap() {
     158             :     FindTargetMaps();
     159     1142710 :     return !target_maps_.empty() ? *target_maps_[0] : nullptr;
     160             :   }
     161             : 
     162     5706623 :   Handle<FeedbackVector> vector() const { return nexus()->vector_handle(); }
     163             :   FeedbackSlot slot() const { return nexus()->slot(); }
     164             :   State saved_state() const {
     165             :     return state() == RECOMPUTE_HANDLER ? old_state_ : state();
     166             :   }
     167             : 
     168             :   template <class NexusClass>
     169             :   NexusClass* casted_nexus() {
     170             :     return static_cast<NexusClass*>(nexus_);
     171             :   }
     172             :   FeedbackNexus* nexus() const { return nexus_; }
     173             : 
     174             :  private:
     175             :   inline Address constant_pool() const;
     176             :   inline Address raw_constant_pool() const;
     177             : 
     178      940733 :   void FindTargetMaps() {
     179     1465559 :     if (target_maps_set_) return;
     180      940733 :     target_maps_set_ = true;
     181      940733 :     nexus()->ExtractMaps(&target_maps_);
     182             :   }
     183             : 
     184             :   // Frame pointer for the frame that uses (calls) the IC.
     185             :   Address fp_;
     186             : 
     187             :   // All access to the program counter and constant pool of an IC structure is
     188             :   // indirect to make the code GC safe. This feature is crucial since
     189             :   // GetProperty and SetProperty are called and they in turn might
     190             :   // invoke the garbage collector.
     191             :   Address* pc_address_;
     192             : 
     193             :   // The constant pool of the code which originally called the IC (which might
     194             :   // be for the breakpointed copy of the original code).
     195             :   Address* constant_pool_address_;
     196             : 
     197             :   Isolate* isolate_;
     198             : 
     199             :   bool vector_set_;
     200             :   State old_state_;  // For saving if we marked as prototype failure.
     201             :   State state_;
     202             :   FeedbackSlotKind kind_;
     203             :   Handle<Map> receiver_map_;
     204             :   MaybeHandle<Object> maybe_handler_;
     205             : 
     206             :   MapHandles target_maps_;
     207             :   bool target_maps_set_;
     208             : 
     209             :   const char* slow_stub_reason_;
     210             : 
     211             :   FeedbackNexus* nexus_;
     212             : 
     213             :   DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
     214             : };
     215             : 
     216             : 
     217           0 : class CallIC : public IC {
     218             :  public:
     219             :   CallIC(Isolate* isolate, CallICNexus* nexus)
     220             :       : IC(EXTRA_CALL_FRAME, isolate, nexus) {
     221             :     DCHECK_NOT_NULL(nexus);
     222             :   }
     223             : };
     224             : 
     225             : 
     226     5884628 : class LoadIC : public IC {
     227             :  public:
     228     1860455 :   LoadIC(Isolate* isolate, FeedbackNexus* nexus)
     229     4024176 :       : IC(NO_EXTRA_FRAME, isolate, nexus) {
     230             :     DCHECK_NOT_NULL(nexus);
     231             :     DCHECK(IsAnyLoad());
     232     1860455 :   }
     233             : 
     234        6437 :   static bool ShouldThrowReferenceError(FeedbackSlotKind kind) {
     235        6437 :     return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
     236             :   }
     237             : 
     238             :   bool ShouldThrowReferenceError() const {
     239      377940 :     return ShouldThrowReferenceError(kind());
     240             :   }
     241             : 
     242             :   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     243             :                                            Handle<Name> name);
     244             : 
     245             :  protected:
     246        4250 :   virtual Handle<Code> slow_stub() const {
     247        4250 :     return BUILTIN_CODE(isolate(), LoadIC_Slow);
     248             :   }
     249             : 
     250             :   // Update the inline cache and the global stub cache based on the
     251             :   // lookup result.
     252             :   void UpdateCaches(LookupIterator* lookup);
     253             : 
     254             :   Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) override;
     255             : 
     256             :   Handle<Code> CompileHandler(LookupIterator* lookup) override;
     257             : 
     258             :  private:
     259             :   // Creates a data handler that represents a load of a field by given index.
     260             :   static Handle<Smi> SimpleFieldLoad(Isolate* isolate, FieldIndex index);
     261             : 
     262             :   friend class IC;
     263             :   friend class NamedLoadHandlerCompiler;
     264             : };
     265             : 
     266     3765738 : class LoadGlobalIC : public LoadIC {
     267             :  public:
     268     1882870 :   LoadGlobalIC(Isolate* isolate, FeedbackNexus* nexus)
     269     1882871 :       : LoadIC(isolate, nexus) {}
     270             : 
     271             :   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Name> name);
     272             : 
     273             :  protected:
     274         555 :   Handle<Code> slow_stub() const override {
     275         555 :     return BUILTIN_CODE(isolate(), LoadGlobalIC_Slow);
     276             :   }
     277             : };
     278             : 
     279      561702 : class KeyedLoadIC : public LoadIC {
     280             :  public:
     281      280851 :   KeyedLoadIC(Isolate* isolate, KeyedLoadICNexus* nexus)
     282      280851 :       : LoadIC(isolate, nexus) {
     283             :     DCHECK_NOT_NULL(nexus);
     284      280851 :   }
     285             : 
     286             :   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
     287             :                                            Handle<Object> key);
     288             : 
     289             :  protected:
     290             :   // receiver is HeapObject because it could be a String or a JSObject
     291             :   void UpdateLoadElement(Handle<HeapObject> receiver);
     292             : 
     293             :  private:
     294             :   friend class IC;
     295             : 
     296             :   Handle<Object> LoadElementHandler(Handle<Map> receiver_map);
     297             : 
     298             :   void LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
     299             :                                       ObjectHandles* handlers);
     300             : };
     301             : 
     302             : 
     303     7319313 : class StoreIC : public IC {
     304             :  public:
     305     2745158 :   StoreIC(Isolate* isolate, FeedbackNexus* nexus)
     306     4574157 :       : IC(NO_EXTRA_FRAME, isolate, nexus) {
     307             :     DCHECK(IsAnyStore());
     308     2745158 :   }
     309             : 
     310     4674646 :   LanguageMode language_mode() const {
     311     9349292 :     return nexus()->vector()->GetLanguageMode(nexus()->slot());
     312             :   }
     313             : 
     314             :   MUST_USE_RESULT MaybeHandle<Object> Store(
     315             :       Handle<Object> object, Handle<Name> name, Handle<Object> value,
     316             :       JSReceiver::StoreFromKeyed store_mode =
     317             :           JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
     318             : 
     319             :   bool LookupForWrite(LookupIterator* it, Handle<Object> value,
     320             :                       JSReceiver::StoreFromKeyed store_mode);
     321             : 
     322             :  protected:
     323             :   // Stub accessors.
     324      142196 :   virtual Handle<Code> slow_stub() const {
     325             :     // All StoreICs share the same slow stub.
     326      142196 :     return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
     327             :   }
     328             : 
     329             :   // Update the inline cache and the global stub cache based on the
     330             :   // lookup result.
     331             :   void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
     332             :                     JSReceiver::StoreFromKeyed store_mode,
     333             :                     MaybeHandle<Object> cached_handler);
     334             :   Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) override;
     335             :   Handle<Code> CompileHandler(LookupIterator* lookup) override;
     336             : 
     337             :  private:
     338             :   friend class IC;
     339             : 
     340             :   bool created_new_transition_ = false;
     341             : };
     342             : 
     343     3016274 : class StoreGlobalIC : public StoreIC {
     344             :  public:
     345     1508137 :   StoreGlobalIC(Isolate* isolate, FeedbackNexus* nexus)
     346     1508137 :       : StoreIC(isolate, nexus) {}
     347             : 
     348             :   MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
     349             :                                             Handle<Name> name,
     350             :                                             Handle<Object> value);
     351             : 
     352             :  protected:
     353         250 :   Handle<Code> slow_stub() const override {
     354         250 :     return BUILTIN_CODE(isolate(), StoreGlobalIC_Slow);
     355             :   }
     356             : };
     357             : 
     358             : enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
     359             : 
     360             : 
     361             : enum KeyedStoreIncrementLength { kDontIncrementLength, kIncrementLength };
     362             : 
     363             : 
     364      641724 : class KeyedStoreIC : public StoreIC {
     365             :  public:
     366             :   KeyedAccessStoreMode GetKeyedAccessStoreMode() {
     367       13583 :     return casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
     368             :   }
     369             : 
     370      320862 :   KeyedStoreIC(Isolate* isolate, KeyedStoreICNexus* nexus)
     371      320862 :       : StoreIC(isolate, nexus) {}
     372             : 
     373             :   MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
     374             :                                             Handle<Object> name,
     375             :                                             Handle<Object> value);
     376             : 
     377             :  protected:
     378             :   void UpdateStoreElement(Handle<Map> receiver_map,
     379             :                           KeyedAccessStoreMode store_mode);
     380             : 
     381             :  private:
     382             :   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
     383             :                                      KeyedAccessStoreMode store_mode);
     384             : 
     385             :   Handle<Object> StoreElementHandler(Handle<Map> receiver_map,
     386             :                                      KeyedAccessStoreMode store_mode);
     387             : 
     388             :   void StoreElementPolymorphicHandlers(MapHandles* receiver_maps,
     389             :                                        ObjectHandles* handlers,
     390             :                                        KeyedAccessStoreMode store_mode);
     391             : 
     392             :   friend class IC;
     393             : };
     394             : 
     395             : }  // namespace internal
     396             : }  // namespace v8
     397             : 
     398             : #endif  // V8_IC_H_

Generated by: LCOV version 1.10