LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 32 32 100.0 %
Date: 2017-10-20 Functions: 11 11 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_SRC_IC_ACCESSOR_ASSEMBLER_H_
       6             : #define V8_SRC_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             : class AccessorAssembler : public CodeStubAssembler {
      20             :  public:
      21             :   typedef compiler::Node Node;
      22             : 
      23             :   explicit AccessorAssembler(compiler::CodeAssemblerState* state)
      24        1103 :       : CodeStubAssembler(state) {}
      25             : 
      26             :   void GenerateLoadIC();
      27             :   void GenerateLoadIC_Noninlined();
      28             :   void GenerateLoadIC_Uninitialized();
      29             :   void GenerateLoadField();
      30             :   void GenerateLoadICTrampoline();
      31             :   void GenerateKeyedLoadIC();
      32             :   void GenerateKeyedLoadICTrampoline();
      33             :   void GenerateKeyedLoadIC_Megamorphic();
      34             :   void GenerateKeyedLoadIC_PolymorphicName();
      35             :   void GenerateStoreIC();
      36             :   void GenerateStoreICTrampoline();
      37             : 
      38             :   void GenerateLoadICProtoArray(bool throw_reference_error_if_nonexistent);
      39             : 
      40             :   void GenerateLoadGlobalIC(TypeofMode typeof_mode);
      41             :   void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
      42             : 
      43             :   void GenerateKeyedStoreIC();
      44             :   void GenerateKeyedStoreICTrampoline();
      45             : 
      46             :   void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
      47             :                          Label* if_handler, Variable* var_handler,
      48             :                          Label* if_miss);
      49             : 
      50             :   Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
      51          12 :     return StubCachePrimaryOffset(name, map);
      52             :   }
      53             :   Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) {
      54           6 :     return StubCacheSecondaryOffset(name, map);
      55             :   }
      56             : 
      57             :   struct LoadICParameters {
      58             :     LoadICParameters(Node* context, Node* receiver, Node* name, Node* slot,
      59             :                      Node* vector)
      60             :         : context(context),
      61             :           receiver(receiver),
      62             :           name(name),
      63             :           slot(slot),
      64        1271 :           vector(vector) {}
      65             : 
      66             :     Node* context;
      67             :     Node* receiver;
      68             :     Node* name;
      69             :     Node* slot;
      70             :     Node* vector;
      71             :   };
      72             : 
      73             :   void LoadGlobalIC_TryPropertyCellCase(
      74             :       Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler,
      75             :       Label* miss, ParameterMode slot_mode = SMI_PARAMETERS);
      76             :   void LoadGlobalIC_TryHandlerCase(const LoadICParameters* p,
      77             :                                    TypeofMode typeof_mode,
      78             :                                    ExitPoint* exit_point, Label* miss);
      79             :   void LoadGlobalIC_MissCase(const LoadICParameters* p, ExitPoint* exit_point);
      80             : 
      81             :   // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame
      82             :   // construction on common paths.
      83             :   void LoadIC_BytecodeHandler(const LoadICParameters* p, ExitPoint* exit_point);
      84             : 
      85             :  protected:
      86             :   struct StoreICParameters : public LoadICParameters {
      87             :     StoreICParameters(Node* context, Node* receiver, Node* name, Node* value,
      88             :                       Node* slot, Node* vector)
      89             :         : LoadICParameters(context, receiver, name, slot, vector),
      90         124 :           value(value) {}
      91             :     Node* value;
      92             :   };
      93             : 
      94             :   enum ElementSupport { kOnlyProperties, kSupportElements };
      95             :   void HandleStoreICHandlerCase(
      96             :       const StoreICParameters* p, Node* handler, Label* miss,
      97             :       ElementSupport support_elements = kOnlyProperties);
      98             :   void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
      99             : 
     100             :   void BranchIfStrictMode(Node* vector, Node* slot, Label* if_strict);
     101             : 
     102             :  private:
     103             :   // Stub generation entry points.
     104             : 
     105             :   // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains
     106             :   // logic not inlined into Ignition bytecode handlers.
     107             :   void LoadIC(const LoadICParameters* p);
     108             :   void LoadIC_Noninlined(const LoadICParameters* p, Node* receiver_map,
     109             :                          Node* feedback, Variable* var_handler,
     110             :                          Label* if_handler, Label* miss, ExitPoint* exit_point);
     111             : 
     112             :   void LoadIC_Uninitialized(const LoadICParameters* p);
     113             :   void LoadICProtoArray(const LoadICParameters* p, Node* handler,
     114             :                         bool throw_reference_error_if_nonexistent);
     115             :   void LoadGlobalIC(const LoadICParameters* p, TypeofMode typeof_mode);
     116             :   void KeyedLoadIC(const LoadICParameters* p);
     117             :   void KeyedLoadICGeneric(const LoadICParameters* p);
     118             :   void KeyedLoadICPolymorphicName(const LoadICParameters* p);
     119             :   void StoreIC(const StoreICParameters* p);
     120             :   void StoreGlobalIC_PropertyCellCase(Node* property_cell, Node* value,
     121             :                                       ExitPoint* exit_point, Label* miss);
     122             :   void KeyedStoreIC(const StoreICParameters* p);
     123             : 
     124             :   // IC dispatcher behavior.
     125             : 
     126             :   // Checks monomorphic case. Returns {feedback} entry of the vector.
     127             :   Node* TryMonomorphicCase(Node* slot, Node* vector, Node* receiver_map,
     128             :                            Label* if_handler, Variable* var_handler,
     129             :                            Label* if_miss);
     130             :   void HandlePolymorphicCase(Node* receiver_map, Node* feedback,
     131             :                              Label* if_handler, Variable* var_handler,
     132             :                              Label* if_miss, int min_feedback_capacity);
     133             : 
     134             :   // LoadIC implementation.
     135             : 
     136             :   void HandleLoadICHandlerCase(
     137             :       const LoadICParameters* p, Node* handler, Label* miss,
     138             :       ExitPoint* exit_point, ElementSupport support_elements = kOnlyProperties);
     139             : 
     140             :   void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder,
     141             :                                   Node* smi_handler, Label* miss,
     142             :                                   ExitPoint* exit_point,
     143             :                                   bool throw_reference_error_if_nonexistent,
     144             :                                   ElementSupport support_elements);
     145             : 
     146             :   void HandleLoadICProtoHandlerCase(const LoadICParameters* p, Node* handler,
     147             :                                     Variable* var_holder,
     148             :                                     Variable* var_smi_handler,
     149             :                                     Label* if_smi_handler, Label* miss,
     150             :                                     ExitPoint* exit_point,
     151             :                                     bool throw_reference_error_if_nonexistent);
     152             : 
     153             :   void HandleLoadField(Node* holder, Node* handler_word,
     154             :                        Variable* var_double_value, Label* rebox_double,
     155             :                        ExitPoint* exit_point);
     156             : 
     157             :   void EmitAccessCheck(Node* expected_native_context, Node* context,
     158             :                        Node* receiver, Label* can_access, Label* miss);
     159             : 
     160             :   Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p, Node* handler,
     161             :                                   Node* handler_length, Node* handler_flags,
     162             :                                   Label* miss);
     163             : 
     164             :   // LoadGlobalIC implementation.
     165             : 
     166             :   void HandleLoadGlobalICHandlerCase(const LoadICParameters* p, Node* handler,
     167             :                                      Label* miss, ExitPoint* exit_point,
     168             :                                      bool throw_reference_error_if_nonexistent);
     169             : 
     170             :   // StoreIC implementation.
     171             : 
     172             :   void HandleStoreICElementHandlerCase(const StoreICParameters* p,
     173             :                                        Node* handler, Label* miss);
     174             : 
     175             :   void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler,
     176             :                                  Label* miss, ElementSupport support_elements);
     177             :   // If |transition| is nullptr then the normal field store is generated or
     178             :   // transitioning store otherwise.
     179             :   void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
     180             :                                    Node* value, Node* transition, Label* miss);
     181             :   // If |transition| is nullptr then the normal field store is generated or
     182             :   // transitioning store otherwise.
     183             :   void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
     184             :                                  Representation representation, Node* value,
     185             :                                  Node* transition, Label* miss);
     186             : 
     187             :   void HandleStoreToProxy(const StoreICParameters* p, Node* proxy, Label* miss,
     188             :                           ElementSupport support_elements);
     189             : 
     190             :   // KeyedLoadIC_Generic implementation.
     191             : 
     192             :   void GenericElementLoad(Node* receiver, Node* receiver_map,
     193             :                           Node* instance_type, Node* index, Label* slow);
     194             : 
     195             :   enum UseStubCache { kUseStubCache, kDontUseStubCache };
     196             :   void GenericPropertyLoad(Node* receiver, Node* receiver_map,
     197             :                            Node* instance_type, const LoadICParameters* p,
     198             :                            Label* slow,
     199             :                            UseStubCache use_stub_cache = kUseStubCache);
     200             : 
     201             :   // Low-level helpers.
     202             : 
     203             :   Node* PrepareValueForStore(Node* handler_word, Node* holder,
     204             :                              Representation representation, Node* transition,
     205             :                              Node* value, Label* bailout);
     206             : 
     207             :   // Extends properties backing store by JSObject::kFieldsAdded elements.
     208             :   void ExtendPropertiesBackingStore(Node* object, Node* handler_word);
     209             : 
     210             :   void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
     211             :                        Representation representation, Node* value,
     212             :                        bool transition_to_field, Label* bailout);
     213             : 
     214             :   void EmitFastElementsBoundsCheck(Node* object, Node* elements,
     215             :                                    Node* intptr_index,
     216             :                                    Node* is_jsarray_condition, Label* miss);
     217             :   void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
     218             :                        Node* key, Node* is_jsarray_condition, Label* if_hole,
     219             :                        Label* rebox_double, Variable* var_double_value,
     220             :                        Label* unimplemented_elements_kind, Label* out_of_bounds,
     221             :                        Label* miss, ExitPoint* exit_point);
     222             :   void CheckPrototype(Node* prototype_cell, Node* name, Label* miss);
     223             :   void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss);
     224             : 
     225             :   // Stub cache access helpers.
     226             : 
     227             :   // This enum is used here as a replacement for StubCache::Table to avoid
     228             :   // including stub cache header.
     229             :   enum StubCacheTable : int;
     230             : 
     231             :   Node* StubCachePrimaryOffset(Node* name, Node* map);
     232             :   Node* StubCacheSecondaryOffset(Node* name, Node* seed);
     233             : 
     234             :   void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
     235             :                               Node* entry_offset, Node* name, Node* map,
     236             :                               Label* if_handler, Variable* var_handler,
     237             :                               Label* if_miss);
     238             : };
     239             : 
     240             : // Abstraction over direct and indirect exit points. Direct exits correspond to
     241             : // tailcalls and Return, while indirect exits store the result in a variable
     242             : // and then jump to an exit label.
     243             : class ExitPoint {
     244             :  private:
     245             :   typedef compiler::Node Node;
     246             :   typedef compiler::CodeAssemblerLabel CodeAssemblerLabel;
     247             :   typedef compiler::CodeAssemblerVariable CodeAssemblerVariable;
     248             : 
     249             :  public:
     250             :   explicit ExitPoint(CodeStubAssembler* assembler)
     251             :       : ExitPoint(assembler, nullptr, nullptr) {}
     252             :   ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out,
     253             :             CodeAssemblerVariable* var_result)
     254        1519 :       : out_(out), var_result_(var_result), asm_(assembler) {
     255             :     DCHECK_EQ(out != nullptr, var_result != nullptr);
     256             :   }
     257             : 
     258             :   template <class... TArgs>
     259        3441 :   void ReturnCallRuntime(Runtime::FunctionId function, Node* context,
     260        3441 :                          TArgs... args) {
     261        3441 :     if (IsDirect()) {
     262         930 :       asm_->TailCallRuntime(function, context, args...);
     263             :     } else {
     264        5022 :       IndirectReturn(asm_->CallRuntime(function, context, args...));
     265             :     }
     266        3441 :   }
     267             : 
     268             :   template <class... TArgs>
     269        3162 :   void ReturnCallStub(Callable const& callable, Node* context, TArgs... args) {
     270        3162 :     if (IsDirect()) {
     271        1023 :       asm_->TailCallStub(callable, context, args...);
     272             :     } else {
     273        2139 :       IndirectReturn(asm_->CallStub(callable, context, args...));
     274             :     }
     275        3162 :   }
     276             : 
     277             :   template <class... TArgs>
     278         775 :   void ReturnCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
     279         775 :                       Node* context, TArgs... args) {
     280         775 :     if (IsDirect()) {
     281         217 :       asm_->TailCallStub(descriptor, target, context, args...);
     282             :     } else {
     283        1116 :       IndirectReturn(asm_->CallStub(descriptor, target, context, args...));
     284             :     }
     285         775 :   }
     286             : 
     287       12524 :   void Return(Node* const result) {
     288       12524 :     if (IsDirect()) {
     289        4526 :       asm_->Return(result);
     290             :     } else {
     291        7998 :       IndirectReturn(result);
     292             :     }
     293       12524 :   }
     294             : 
     295             :   bool IsDirect() const { return out_ == nullptr; }
     296             : 
     297             :  private:
     298       13206 :   void IndirectReturn(Node* const result) {
     299       13206 :     var_result_->Bind(result);
     300       13206 :     asm_->Goto(out_);
     301       13206 :   }
     302             : 
     303             :   CodeAssemblerLabel* const out_;
     304             :   CodeAssemblerVariable* const var_result_;
     305             :   CodeStubAssembler* const asm_;
     306             : };
     307             : 
     308             : }  // namespace internal
     309             : }  // namespace v8
     310             : 
     311             : #endif  // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_

Generated by: LCOV version 1.10