Home | History | Annotate | Download | only in ic
      1 // Copyright 2014 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_HANDLER_COMPILER_H_
      6 #define V8_IC_HANDLER_COMPILER_H_
      7 
      8 #include "src/ic/access-compiler.h"
      9 #include "src/ic/ic-state.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 class CallOptimization;
     15 
     16 enum ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
     17 
     18 class PropertyHandlerCompiler : public PropertyAccessCompiler {
     19  public:
     20   static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
     21                            CacheHolderFlag cache_holder);
     22 
     23  protected:
     24   PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
     25                           Handle<JSObject> holder, CacheHolderFlag cache_holder)
     26       : PropertyAccessCompiler(isolate, kind, cache_holder),
     27         map_(map),
     28         holder_(holder) {}
     29 
     30   virtual ~PropertyHandlerCompiler() {}
     31 
     32   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
     33                                   Label* miss, ReturnHolder return_what) {
     34     UNREACHABLE();
     35     return receiver();
     36   }
     37 
     38   virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
     39 
     40   // Frontend loads from receiver(), returns holder register which may be
     41   // different.
     42   Register Frontend(Handle<Name> name);
     43 
     44   // When FLAG_vector_ics is true, handlers that have the possibility of missing
     45   // will need to save and pass these to miss handlers.
     46   void PushVectorAndSlot() { PushVectorAndSlot(vector(), slot()); }
     47   void PushVectorAndSlot(Register vector, Register slot);
     48   void PopVectorAndSlot() { PopVectorAndSlot(vector(), slot()); }
     49   void PopVectorAndSlot(Register vector, Register slot);
     50 
     51   void DiscardVectorAndSlot();
     52 
     53   // TODO(verwaest): Make non-static.
     54   static void GenerateApiAccessorCall(MacroAssembler* masm,
     55                                       const CallOptimization& optimization,
     56                                       Handle<Map> receiver_map,
     57                                       Register receiver, Register scratch,
     58                                       bool is_store, Register store_parameter,
     59                                       Register accessor_holder,
     60                                       int accessor_index);
     61 
     62   // Helper function used to check that the dictionary doesn't contain
     63   // the property. This function may return false negatives, so miss_label
     64   // must always call a backup property check that is complete.
     65   // This function is safe to call if the receiver has fast properties.
     66   // Name must be unique and receiver must be a heap object.
     67   static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
     68                                                Label* miss_label,
     69                                                Register receiver,
     70                                                Handle<Name> name, Register r0,
     71                                                Register r1);
     72 
     73   // Generate code to check that a global property cell is empty. Create
     74   // the property cell at compilation time if no cell exists for the
     75   // property.
     76   static void GenerateCheckPropertyCell(MacroAssembler* masm,
     77                                         Handle<JSGlobalObject> global,
     78                                         Handle<Name> name, Register scratch,
     79                                         Label* miss);
     80 
     81   // Generates check that current native context has the same access rights
     82   // as the given |native_context_cell|.
     83   // If |compare_native_contexts_only| is true then access check is considered
     84   // passed if the execution-time native context is equal to contents of
     85   // |native_context_cell|.
     86   // If |compare_native_contexts_only| is false then access check is considered
     87   // passed if the execution-time native context is equal to contents of
     88   // |native_context_cell| or security tokens of both contexts are equal.
     89   void GenerateAccessCheck(Handle<WeakCell> native_context_cell,
     90                            Register scratch1, Register scratch2, Label* miss,
     91                            bool compare_native_contexts_only);
     92 
     93   // Generates code that verifies that the property holder has not changed
     94   // (checking maps of objects in the prototype chain for fast and global
     95   // objects or doing negative lookup for slow objects, ensures that the
     96   // property cells for global objects are still empty) and checks that the map
     97   // of the holder has not changed. If necessary the function also generates
     98   // code for security check in case of global object holders. Helps to make
     99   // sure that the current IC is still valid.
    100   //
    101   // The scratch and holder registers are always clobbered, but the object
    102   // register is only clobbered if it the same as the holder register. The
    103   // function returns a register containing the holder - either object_reg or
    104   // holder_reg.
    105   Register CheckPrototypes(Register object_reg, Register holder_reg,
    106                            Register scratch1, Register scratch2,
    107                            Handle<Name> name, Label* miss,
    108                            ReturnHolder return_what);
    109 
    110   Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
    111   void set_holder(Handle<JSObject> holder) { holder_ = holder; }
    112   Handle<Map> map() const { return map_; }
    113   void set_map(Handle<Map> map) { map_ = map; }
    114   Handle<JSObject> holder() const { return holder_; }
    115 
    116  private:
    117   Handle<Map> map_;
    118   Handle<JSObject> holder_;
    119 };
    120 
    121 
    122 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
    123  public:
    124   NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
    125                            Handle<JSObject> holder,
    126                            CacheHolderFlag cache_holder)
    127       : PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder,
    128                                 cache_holder) {}
    129 
    130   virtual ~NamedLoadHandlerCompiler() {}
    131 
    132   Handle<Code> CompileLoadCallback(Handle<Name> name,
    133                                    Handle<AccessorInfo> callback,
    134                                    Handle<Code> slow_stub);
    135 
    136   Handle<Code> CompileLoadCallback(Handle<Name> name,
    137                                    const CallOptimization& call_optimization,
    138                                    int accessor_index, Handle<Code> slow_stub);
    139 
    140   // The LookupIterator is used to perform a lookup behind the interceptor. If
    141   // the iterator points to a LookupIterator::PROPERTY, its access will be
    142   // inlined.
    143   Handle<Code> CompileLoadInterceptor(LookupIterator* it);
    144 
    145   Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
    146                                     int expected_arguments);
    147 
    148   Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
    149                                  bool is_configurable);
    150 
    151   static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
    152                                     Register receiver, Register holder,
    153                                     int accessor_index, int expected_arguments,
    154                                     Register scratch);
    155 
    156   static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
    157     GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
    158                           no_reg);
    159   }
    160 
    161   // These constants describe the structure of the interceptor arguments on the
    162   // stack. The arguments are pushed by the (platform-specific)
    163   // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
    164   // LoadWithInterceptor.
    165   static const int kInterceptorArgsNameIndex = 0;
    166   static const int kInterceptorArgsThisIndex = 1;
    167   static const int kInterceptorArgsHolderIndex = 2;
    168   static const int kInterceptorArgsLength = 3;
    169 
    170  protected:
    171   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
    172                                   Label* miss, ReturnHolder return_what);
    173 
    174   virtual void FrontendFooter(Handle<Name> name, Label* miss);
    175 
    176  private:
    177   void GenerateLoadCallback(Register reg, Handle<AccessorInfo> callback);
    178 
    179   // Helper emits no code if vector-ics are disabled.
    180   void InterceptorVectorSlotPush(Register holder_reg);
    181   enum PopMode { POP, DISCARD };
    182   void InterceptorVectorSlotPop(Register holder_reg, PopMode mode = POP);
    183 
    184   void GenerateLoadInterceptor(Register holder_reg);
    185   void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
    186                                            Register holder_reg);
    187   void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
    188 
    189   Register scratch3() { return registers_[4]; }
    190 };
    191 
    192 
    193 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
    194  public:
    195   // All store handlers use StoreWithVectorDescriptor calling convention.
    196   typedef StoreWithVectorDescriptor Descriptor;
    197 
    198   explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
    199                                      Handle<JSObject> holder)
    200       : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
    201                                 kCacheOnReceiver) {
    202 #ifdef DEBUG
    203     if (Descriptor::kPassLastArgsOnStack) {
    204       ZapStackArgumentsRegisterAliases();
    205     }
    206 #endif
    207   }
    208 
    209   virtual ~NamedStoreHandlerCompiler() {}
    210 
    211   void ZapStackArgumentsRegisterAliases();
    212 
    213   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
    214                                     Handle<AccessorInfo> callback,
    215                                     LanguageMode language_mode);
    216   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
    217                                     const CallOptimization& call_optimization,
    218                                     int accessor_index, Handle<Code> slow_stub);
    219   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
    220                                      int accessor_index,
    221                                      int expected_arguments);
    222 
    223   static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
    224                                      Register receiver, Register holder,
    225                                      int accessor_index, int expected_arguments,
    226                                      Register scratch);
    227 
    228   static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
    229     GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
    230                            no_reg);
    231   }
    232 
    233  protected:
    234   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
    235                                   Label* miss, ReturnHolder return_what);
    236 
    237   virtual void FrontendFooter(Handle<Name> name, Label* miss);
    238   void GenerateRestoreName(Label* label, Handle<Name> name);
    239 
    240  private:
    241   static Register value();
    242 };
    243 
    244 
    245 class ElementHandlerCompiler : public PropertyHandlerCompiler {
    246  public:
    247   explicit ElementHandlerCompiler(Isolate* isolate)
    248       : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
    249                                 Handle<Map>::null(), Handle<JSObject>::null(),
    250                                 kCacheOnReceiver) {}
    251 
    252   virtual ~ElementHandlerCompiler() {}
    253 
    254   static Handle<Object> GetKeyedLoadHandler(Handle<Map> receiver_map,
    255                                             Isolate* isolate);
    256   void CompileElementHandlers(MapHandleList* receiver_maps,
    257                               List<Handle<Object>>* handlers);
    258 };
    259 }  // namespace internal
    260 }  // namespace v8
    261 
    262 #endif  // V8_IC_HANDLER_COMPILER_H_
    263