LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 33 33 100.0 %
Date: 2019-04-18 Functions: 18 18 100.0 %

          Line data    Source code
       1             : // Copyright 2016 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_ACCESSOR_ASSEMBLER_H_
       6             : #define V8_IC_ACCESSOR_ASSEMBLER_H_
       7             : 
       8             : #include "src/code-stub-assembler.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13             : namespace compiler {
      14             : class CodeAssemblerState;
      15             : }
      16             : 
      17             : class ExitPoint;
      18             : 
      19        2700 : class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
      20             :  public:
      21             :   using Node = compiler::Node;
      22             :   template <class T>
      23             :   using TNode = compiler::TNode<T>;
      24             :   template <class T>
      25             :   using SloppyTNode = compiler::SloppyTNode<T>;
      26             : 
      27             :   explicit AccessorAssembler(compiler::CodeAssemblerState* state)
      28        2644 :       : CodeStubAssembler(state) {}
      29             : 
      30             :   void GenerateLoadIC();
      31             :   void GenerateLoadIC_Megamorphic();
      32             :   void GenerateLoadIC_Noninlined();
      33             :   void GenerateLoadIC_Uninitialized();
      34             :   void GenerateLoadICTrampoline();
      35             :   void GenerateLoadICTrampoline_Megamorphic();
      36             :   void GenerateKeyedLoadIC();
      37             :   void GenerateKeyedLoadIC_Megamorphic();
      38             :   void GenerateKeyedLoadIC_PolymorphicName();
      39             :   void GenerateKeyedLoadICTrampoline();
      40             :   void GenerateKeyedLoadICTrampoline_Megamorphic();
      41             :   void GenerateStoreIC();
      42             :   void GenerateStoreICTrampoline();
      43             :   void GenerateStoreGlobalIC();
      44             :   void GenerateStoreGlobalICTrampoline();
      45             :   void GenerateCloneObjectIC();
      46             :   void GenerateCloneObjectIC_Slow();
      47             :   void GenerateKeyedHasIC();
      48             :   void GenerateKeyedHasIC_Megamorphic();
      49             :   void GenerateKeyedHasIC_PolymorphicName();
      50             : 
      51             :   void GenerateLoadGlobalIC(TypeofMode typeof_mode);
      52             :   void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
      53             : 
      54             :   void GenerateKeyedStoreIC();
      55             :   void GenerateKeyedStoreICTrampoline();
      56             : 
      57             :   void GenerateStoreInArrayLiteralIC();
      58             : 
      59             :   void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
      60             :                          Label* if_handler, TVariable<MaybeObject>* var_handler,
      61             :                          Label* if_miss);
      62             : 
      63             :   Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
      64           8 :     return StubCachePrimaryOffset(name, map);
      65             :   }
      66             :   Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) {
      67           4 :     return StubCacheSecondaryOffset(name, map);
      68             :   }
      69             : 
      70             :   struct LoadICParameters {
      71             :     LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot,
      72             :                      Node* vector, Node* holder = nullptr)
      73             :         : context(context),
      74             :           receiver(receiver),
      75             :           name(name),
      76             :           slot(slot),
      77             :           vector(vector),
      78        1960 :           holder(holder ? holder : receiver) {}
      79             : 
      80             :     Node* context;
      81             :     Node* receiver;
      82             :     Node* name;
      83             :     Node* slot;
      84             :     Node* vector;
      85             :     Node* holder;
      86             :   };
      87             : 
      88             :   void LoadGlobalIC(Node* vector, Node* slot,
      89             :                     const LazyNode<Context>& lazy_context,
      90             :                     const LazyNode<Name>& lazy_name, TypeofMode typeof_mode,
      91             :                     ExitPoint* exit_point,
      92             :                     ParameterMode slot_mode = SMI_PARAMETERS);
      93             : 
      94             :   // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame
      95             :   // construction on common paths.
      96             :   void LoadIC_BytecodeHandler(const LoadICParameters* p, ExitPoint* exit_point);
      97             : 
      98             :   // Loads dataX field from the DataHandler object.
      99             :   TNode<MaybeObject> LoadHandlerDataField(SloppyTNode<DataHandler> handler,
     100             :                                           int data_index);
     101             : 
     102             :  protected:
     103             :   struct StoreICParameters : public LoadICParameters {
     104             :     StoreICParameters(Node* context, Node* receiver, Node* name,
     105             :                       SloppyTNode<Object> value, Node* slot, Node* vector)
     106             :         : LoadICParameters(context, receiver, name, slot, vector),
     107         504 :           value(value) {}
     108             :     SloppyTNode<Object> value;
     109             :   };
     110             : 
     111             :   enum class LoadAccessMode { kLoad, kHas };
     112             :   enum class ICMode { kNonGlobalIC, kGlobalIC };
     113             :   enum ElementSupport { kOnlyProperties, kSupportElements };
     114             :   void HandleStoreICHandlerCase(
     115             :       const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
     116             :       ICMode ic_mode, ElementSupport support_elements = kOnlyProperties);
     117             :   enum StoreTransitionMapFlags {
     118             :     kCheckPrototypeValidity = 1 << 0,
     119             :     kValidateTransitionHandler = 1 << 1,
     120             :     kStoreTransitionMapFlagsMask =
     121             :         kCheckPrototypeValidity | kValidateTransitionHandler,
     122             :   };
     123             :   void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p,
     124             :                                              TNode<Map> transition_map,
     125             :                                              Label* miss,
     126             :                                              StoreTransitionMapFlags flags);
     127             : 
     128             :   void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
     129             : 
     130             :   void InvalidateValidityCellIfPrototype(Node* map, Node* bitfield2 = nullptr);
     131             : 
     132             :   void OverwriteExistingFastDataProperty(Node* object, Node* object_map,
     133             :                                          Node* descriptors,
     134             :                                          Node* descriptor_name_index,
     135             :                                          Node* details, Node* value,
     136             :                                          Label* slow,
     137             :                                          bool do_transitioning_store);
     138             : 
     139             :   void CheckFieldType(TNode<DescriptorArray> descriptors, Node* name_index,
     140             :                       Node* representation, Node* value, Label* bailout);
     141             : 
     142             :  private:
     143             :   // Stub generation entry points.
     144             : 
     145             :   // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains
     146             :   // logic not inlined into Ignition bytecode handlers.
     147             :   void LoadIC(const LoadICParameters* p);
     148             :   void LoadIC_Noninlined(const LoadICParameters* p, Node* receiver_map,
     149             :                          TNode<HeapObject> feedback,
     150             :                          TVariable<MaybeObject>* var_handler, Label* if_handler,
     151             :                          Label* miss, ExitPoint* exit_point);
     152             : 
     153             :   TNode<Object> LoadDescriptorValue(TNode<Map> map,
     154             :                                     TNode<IntPtrT> descriptor_entry);
     155             :   TNode<MaybeObject> LoadDescriptorValueOrFieldType(
     156             :       TNode<Map> map, TNode<IntPtrT> descriptor_entry);
     157             : 
     158             :   void LoadIC_Uninitialized(const LoadICParameters* p);
     159             : 
     160             :   void KeyedLoadIC(const LoadICParameters* p, LoadAccessMode access_mode);
     161             :   void KeyedLoadICGeneric(const LoadICParameters* p);
     162             :   void KeyedLoadICPolymorphicName(const LoadICParameters* p,
     163             :                                   LoadAccessMode access_mode);
     164             :   void StoreIC(const StoreICParameters* p);
     165             :   void StoreGlobalIC(const StoreICParameters* p);
     166             :   void StoreGlobalIC_PropertyCellCase(Node* property_cell, Node* value,
     167             :                                       ExitPoint* exit_point, Label* miss);
     168             :   void KeyedStoreIC(const StoreICParameters* p);
     169             :   void StoreInArrayLiteralIC(const StoreICParameters* p);
     170             : 
     171             :   // IC dispatcher behavior.
     172             : 
     173             :   // Checks monomorphic case. Returns {feedback} entry of the vector.
     174             :   TNode<MaybeObject> TryMonomorphicCase(Node* slot, Node* vector,
     175             :                                         Node* receiver_map, Label* if_handler,
     176             :                                         TVariable<MaybeObject>* var_handler,
     177             :                                         Label* if_miss);
     178             :   void HandlePolymorphicCase(Node* receiver_map, TNode<WeakFixedArray> feedback,
     179             :                              Label* if_handler,
     180             :                              TVariable<MaybeObject>* var_handler,
     181             :                              Label* if_miss);
     182             : 
     183             :   // LoadIC implementation.
     184             :   void HandleLoadICHandlerCase(
     185             :       const LoadICParameters* p, TNode<Object> handler, Label* miss,
     186             :       ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC,
     187             :       OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined,
     188             :       ElementSupport support_elements = kOnlyProperties,
     189             :       LoadAccessMode access_mode = LoadAccessMode::kLoad);
     190             : 
     191             :   void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder,
     192             :                                   SloppyTNode<Smi> smi_handler,
     193             :                                   SloppyTNode<Object> handler, Label* miss,
     194             :                                   ExitPoint* exit_point,
     195             :                                   OnNonExistent on_nonexistent,
     196             :                                   ElementSupport support_elements,
     197             :                                   LoadAccessMode access_mode);
     198             : 
     199             :   void HandleLoadICProtoHandler(const LoadICParameters* p, Node* handler,
     200             :                                 Variable* var_holder, Variable* var_smi_handler,
     201             :                                 Label* if_smi_handler, Label* miss,
     202             :                                 ExitPoint* exit_point, ICMode ic_mode,
     203             :                                 LoadAccessMode access_mode);
     204             : 
     205             :   void HandleLoadCallbackProperty(const LoadICParameters* p,
     206             :                                   TNode<JSObject> holder,
     207             :                                   TNode<WordT> handler_word,
     208             :                                   ExitPoint* exit_point);
     209             : 
     210             :   void HandleLoadAccessor(const LoadICParameters* p,
     211             :                           TNode<CallHandlerInfo> call_handler_info,
     212             :                           TNode<WordT> handler_word, TNode<DataHandler> handler,
     213             :                           TNode<IntPtrT> handler_kind, ExitPoint* exit_point);
     214             : 
     215             :   void HandleLoadField(Node* holder, Node* handler_word,
     216             :                        Variable* var_double_value, Label* rebox_double,
     217             :                        ExitPoint* exit_point);
     218             : 
     219             :   void EmitAccessCheck(Node* expected_native_context, Node* context,
     220             :                        Node* receiver, Label* can_access, Label* miss);
     221             : 
     222             :   void HandleLoadICSmiHandlerLoadNamedCase(
     223             :       const LoadICParameters* p, Node* holder, TNode<IntPtrT> handler_kind,
     224             :       TNode<WordT> handler_word, Label* rebox_double,
     225             :       Variable* var_double_value, SloppyTNode<Object> handler, Label* miss,
     226             :       ExitPoint* exit_point, OnNonExistent on_nonexistent,
     227             :       ElementSupport support_elements);
     228             : 
     229             :   void HandleLoadICSmiHandlerHasNamedCase(const LoadICParameters* p,
     230             :                                           Node* holder,
     231             :                                           TNode<IntPtrT> handler_kind,
     232             :                                           Label* miss, ExitPoint* exit_point);
     233             : 
     234             :   // LoadGlobalIC implementation.
     235             : 
     236             :   void LoadGlobalIC_TryPropertyCellCase(
     237             :       TNode<FeedbackVector> vector, Node* slot,
     238             :       const LazyNode<Context>& lazy_context, ExitPoint* exit_point,
     239             :       Label* try_handler, Label* miss,
     240             :       ParameterMode slot_mode = SMI_PARAMETERS);
     241             : 
     242             :   void LoadGlobalIC_TryHandlerCase(TNode<FeedbackVector> vector, Node* slot,
     243             :                                    const LazyNode<Context>& lazy_context,
     244             :                                    const LazyNode<Name>& lazy_name,
     245             :                                    TypeofMode typeof_mode,
     246             :                                    ExitPoint* exit_point, Label* miss,
     247             :                                    ParameterMode slot_mode);
     248             : 
     249             :   // StoreIC implementation.
     250             : 
     251             :   void HandleStoreICProtoHandler(const StoreICParameters* p,
     252             :                                  TNode<StoreHandler> handler, Label* miss,
     253             :                                  ICMode ic_mode,
     254             :                                  ElementSupport support_elements);
     255             :   void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
     256             :                                    Node* value, Label* miss);
     257             :   void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
     258             :                                  Representation representation, Node* value,
     259             :                                  Label* miss);
     260             : 
     261             :   void CheckPrototypeValidityCell(Node* maybe_validity_cell, Label* miss);
     262             :   void HandleStoreICNativeDataProperty(const StoreICParameters* p, Node* holder,
     263             :                                        Node* handler_word);
     264             : 
     265             :   void HandleStoreToProxy(const StoreICParameters* p, Node* proxy, Label* miss,
     266             :                           ElementSupport support_elements);
     267             : 
     268             :   void HandleStoreAccessor(const StoreICParameters* p, Node* holder,
     269             :                            Node* handler_word);
     270             : 
     271             :   // KeyedLoadIC_Generic implementation.
     272             : 
     273             :   void GenericElementLoad(Node* receiver, Node* receiver_map,
     274             :                           SloppyTNode<Int32T> instance_type, Node* index,
     275             :                           Label* slow);
     276             : 
     277             :   enum UseStubCache { kUseStubCache, kDontUseStubCache };
     278             :   void GenericPropertyLoad(Node* receiver, Node* receiver_map,
     279             :                            SloppyTNode<Int32T> instance_type,
     280             :                            const LoadICParameters* p, Label* slow,
     281             :                            UseStubCache use_stub_cache = kUseStubCache);
     282             : 
     283             :   // Low-level helpers.
     284             : 
     285             :   using OnCodeHandler = std::function<void(Node* code_handler)>;
     286             :   using OnFoundOnReceiver =
     287             :       std::function<void(Node* properties, Node* name_index)>;
     288             : 
     289             :   template <typename ICHandler, typename ICParameters>
     290             :   Node* HandleProtoHandler(const ICParameters* p, Node* handler,
     291             :                            const OnCodeHandler& on_code_handler,
     292             :                            const OnFoundOnReceiver& on_found_on_receiver,
     293             :                            Label* miss, ICMode ic_mode);
     294             : 
     295             :   Node* PrepareValueForStore(Node* handler_word, Node* holder,
     296             :                              Representation representation, Node* value,
     297             :                              Label* bailout);
     298             : 
     299             :   void BranchIfPrototypeShouldbeFast(Node* receiver_map,
     300             :                                      Label* prototype_not_fast,
     301             :                                      Label* prototype_fast);
     302             : 
     303             :   // Extends properties backing store by JSObject::kFieldsAdded elements,
     304             :   // returns updated properties backing store.
     305             :   Node* ExtendPropertiesBackingStore(Node* object, Node* index);
     306             : 
     307             :   void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
     308             :                        Representation representation, Node* value,
     309             :                        Label* bailout);
     310             : 
     311             :   void EmitFastElementsBoundsCheck(Node* object, Node* elements,
     312             :                                    Node* intptr_index,
     313             :                                    Node* is_jsarray_condition, Label* miss);
     314             :   void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
     315             :                        SloppyTNode<IntPtrT> key, Node* is_jsarray_condition,
     316             :                        Label* if_hole, Label* rebox_double,
     317             :                        Variable* var_double_value,
     318             :                        Label* unimplemented_elements_kind, Label* out_of_bounds,
     319             :                        Label* miss, ExitPoint* exit_point,
     320             :                        LoadAccessMode access_mode = LoadAccessMode::kLoad);
     321             :   void NameDictionaryNegativeLookup(Node* object, SloppyTNode<Name> name,
     322             :                                     Label* miss);
     323             :   TNode<BoolT> IsPropertyDetailsConst(Node* details);
     324             : 
     325             :   // Stub cache access helpers.
     326             : 
     327             :   // This enum is used here as a replacement for StubCache::Table to avoid
     328             :   // including stub cache header.
     329             :   enum StubCacheTable : int;
     330             : 
     331             :   Node* StubCachePrimaryOffset(Node* name, Node* map);
     332             :   Node* StubCacheSecondaryOffset(Node* name, Node* seed);
     333             : 
     334             :   void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
     335             :                               Node* entry_offset, Node* name, Node* map,
     336             :                               Label* if_handler,
     337             :                               TVariable<MaybeObject>* var_handler,
     338             :                               Label* if_miss);
     339             : };
     340             : 
     341             : // Abstraction over direct and indirect exit points. Direct exits correspond to
     342             : // tailcalls and Return, while indirect exits store the result in a variable
     343             : // and then jump to an exit label.
     344        2240 : class ExitPoint {
     345             :  private:
     346             :   using Node = compiler::Node;
     347             :   using CodeAssemblerLabel = compiler::CodeAssemblerLabel;
     348             :   using CodeAssemblerVariable = compiler::CodeAssemblerVariable;
     349             : 
     350             :  public:
     351             :   using IndirectReturnHandler = std::function<void(Node* result)>;
     352             : 
     353             :   explicit ExitPoint(CodeStubAssembler* assembler)
     354             :       : ExitPoint(assembler, nullptr) {}
     355             : 
     356             :   ExitPoint(CodeStubAssembler* assembler,
     357             :             const IndirectReturnHandler& indirect_return_handler)
     358        2240 :       : asm_(assembler), indirect_return_handler_(indirect_return_handler) {}
     359             : 
     360         168 :   ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out,
     361             :             CodeAssemblerVariable* var_result)
     362        3528 :       : ExitPoint(assembler, [=](Node* result) {
     363        3528 :           var_result->Bind(result);
     364        3528 :           assembler->Goto(out);
     365        3696 :         }) {
     366             :     DCHECK_EQ(out != nullptr, var_result != nullptr);
     367         168 :   }
     368             : 
     369             :   template <class... TArgs>
     370        7112 :   void ReturnCallRuntime(Runtime::FunctionId function, Node* context,
     371             :                          TArgs... args) {
     372        7112 :     if (IsDirect()) {
     373        2464 :       asm_->TailCallRuntime(function, context, args...);
     374             :     } else {
     375        4648 :       indirect_return_handler_(asm_->CallRuntime(function, context, args...));
     376             :     }
     377        7112 :   }
     378             : 
     379             :   template <class... TArgs>
     380        3136 :   void ReturnCallStub(Callable const& callable, Node* context, TArgs... args) {
     381        3136 :     if (IsDirect()) {
     382        1288 :       asm_->TailCallStub(callable, context, args...);
     383             :     } else {
     384        3696 :       indirect_return_handler_(asm_->CallStub(callable, context, args...));
     385             :     }
     386        3136 :   }
     387             : 
     388             :   template <class... TArgs>
     389        1568 :   void ReturnCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
     390             :                       Node* context, TArgs... args) {
     391        1568 :     if (IsDirect()) {
     392         560 :       asm_->TailCallStub(descriptor, target, context, args...);
     393             :     } else {
     394        2016 :       indirect_return_handler_(
     395             :           asm_->CallStub(descriptor, target, context, args...));
     396             :     }
     397        1568 :   }
     398             : 
     399       19264 :   void Return(Node* const result) {
     400       19264 :     if (IsDirect()) {
     401        9408 :       asm_->Return(result);
     402             :     } else {
     403             :       indirect_return_handler_(result);
     404             :     }
     405       19264 :   }
     406             : 
     407             :   bool IsDirect() const { return !indirect_return_handler_; }
     408             : 
     409             :  private:
     410             :   CodeStubAssembler* const asm_;
     411             :   IndirectReturnHandler indirect_return_handler_;
     412             : };
     413             : 
     414             : }  // namespace internal
     415             : }  // namespace v8
     416             : 
     417             : #endif  // V8_IC_ACCESSOR_ASSEMBLER_H_

Generated by: LCOV version 1.10