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 PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
     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, Code::StubType type);
     22 
     23  protected:
     24   PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind,
     25                           Handle<HeapType> type, Handle<JSObject> holder,
     26                           CacheHolderFlag cache_holder)
     27       : PropertyAccessCompiler(isolate, kind, cache_holder),
     28         type_(type),
     29         holder_(holder) {}
     30 
     31   virtual ~PropertyHandlerCompiler() {}
     32 
     33   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
     34                                   Label* miss) {
     35     UNREACHABLE();
     36     return receiver();
     37   }
     38 
     39   virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); }
     40 
     41   Register Frontend(Register object_reg, Handle<Name> name);
     42   void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
     43                                  Register scratch1, Register scratch2);
     44 
     45   // TODO(verwaest): Make non-static.
     46   static void GenerateFastApiCall(MacroAssembler* masm,
     47                                   const CallOptimization& optimization,
     48                                   Handle<Map> receiver_map, Register receiver,
     49                                   Register scratch, bool is_store, int argc,
     50                                   Register* values);
     51 
     52   // Helper function used to check that the dictionary doesn't contain
     53   // the property. This function may return false negatives, so miss_label
     54   // must always call a backup property check that is complete.
     55   // This function is safe to call if the receiver has fast properties.
     56   // Name must be unique and receiver must be a heap object.
     57   static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
     58                                                Label* miss_label,
     59                                                Register receiver,
     60                                                Handle<Name> name, Register r0,
     61                                                Register r1);
     62 
     63   // Generate code to check that a global property cell is empty. Create
     64   // the property cell at compilation time if no cell exists for the
     65   // property.
     66   static void GenerateCheckPropertyCell(MacroAssembler* masm,
     67                                         Handle<JSGlobalObject> global,
     68                                         Handle<Name> name, Register scratch,
     69                                         Label* miss);
     70 
     71   // Generates code that verifies that the property holder has not changed
     72   // (checking maps of objects in the prototype chain for fast and global
     73   // objects or doing negative lookup for slow objects, ensures that the
     74   // property cells for global objects are still empty) and checks that the map
     75   // of the holder has not changed. If necessary the function also generates
     76   // code for security check in case of global object holders. Helps to make
     77   // sure that the current IC is still valid.
     78   //
     79   // The scratch and holder registers are always clobbered, but the object
     80   // register is only clobbered if it the same as the holder register. The
     81   // function returns a register containing the holder - either object_reg or
     82   // holder_reg.
     83   Register CheckPrototypes(Register object_reg, Register holder_reg,
     84                            Register scratch1, Register scratch2,
     85                            Handle<Name> name, Label* miss,
     86                            PrototypeCheckType check = CHECK_ALL_MAPS);
     87 
     88   Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
     89   void set_type_for_object(Handle<Object> object);
     90   void set_holder(Handle<JSObject> holder) { holder_ = holder; }
     91   Handle<HeapType> type() const { return type_; }
     92   Handle<JSObject> holder() const { return holder_; }
     93 
     94  private:
     95   Handle<HeapType> type_;
     96   Handle<JSObject> holder_;
     97 };
     98 
     99 
    100 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
    101  public:
    102   NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
    103                            Handle<JSObject> holder,
    104                            CacheHolderFlag cache_holder)
    105       : PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, holder,
    106                                 cache_holder) {}
    107 
    108   virtual ~NamedLoadHandlerCompiler() {}
    109 
    110   Handle<Code> CompileLoadField(Handle<Name> name, FieldIndex index);
    111 
    112   Handle<Code> CompileLoadCallback(Handle<Name> name,
    113                                    Handle<ExecutableAccessorInfo> callback);
    114 
    115   Handle<Code> CompileLoadCallback(Handle<Name> name,
    116                                    const CallOptimization& call_optimization);
    117 
    118   Handle<Code> CompileLoadConstant(Handle<Name> name, int constant_index);
    119 
    120   // The LookupIterator is used to perform a lookup behind the interceptor. If
    121   // the iterator points to a LookupIterator::PROPERTY, its access will be
    122   // inlined.
    123   Handle<Code> CompileLoadInterceptor(LookupIterator* it);
    124 
    125   Handle<Code> CompileLoadViaGetter(Handle<Name> name,
    126                                     Handle<JSFunction> getter);
    127 
    128   Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
    129                                  bool is_configurable);
    130 
    131   // Static interface
    132   static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
    133                                              Handle<HeapType> type);
    134 
    135   static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type,
    136                                     Register receiver,
    137                                     Handle<JSFunction> getter);
    138 
    139   static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
    140     GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg,
    141                           Handle<JSFunction>());
    142   }
    143 
    144   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
    145                                             Register receiver,
    146                                             Register scratch1,
    147                                             Register scratch2,
    148                                             Label* miss_label);
    149 
    150   // These constants describe the structure of the interceptor arguments on the
    151   // stack. The arguments are pushed by the (platform-specific)
    152   // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
    153   // LoadWithInterceptor.
    154   static const int kInterceptorArgsNameIndex = 0;
    155   static const int kInterceptorArgsInfoIndex = 1;
    156   static const int kInterceptorArgsThisIndex = 2;
    157   static const int kInterceptorArgsHolderIndex = 3;
    158   static const int kInterceptorArgsLength = 4;
    159 
    160  protected:
    161   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
    162                                   Label* miss);
    163 
    164   virtual void FrontendFooter(Handle<Name> name, Label* miss);
    165 
    166  private:
    167   Handle<Code> CompileLoadNonexistent(Handle<Name> name);
    168   void GenerateLoadConstant(Handle<Object> value);
    169   void GenerateLoadCallback(Register reg,
    170                             Handle<ExecutableAccessorInfo> callback);
    171   void GenerateLoadCallback(const CallOptimization& call_optimization,
    172                             Handle<Map> receiver_map);
    173   void GenerateLoadInterceptor(Register holder_reg);
    174   void GenerateLoadInterceptorWithFollowup(LookupIterator* it,
    175                                            Register holder_reg);
    176   void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
    177 
    178   // Generates prototype loading code that uses the objects from the
    179   // context we were in when this function was called. If the context
    180   // has changed, a jump to miss is performed. This ties the generated
    181   // code to a particular context and so must not be used in cases
    182   // where the generated code is not allowed to have references to
    183   // objects from a context.
    184   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
    185                                                         int index,
    186                                                         Register prototype,
    187                                                         Label* miss);
    188 
    189 
    190   Register scratch4() { return registers_[5]; }
    191 };
    192 
    193 
    194 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
    195  public:
    196   explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
    197                                      Handle<JSObject> holder)
    198       : PropertyHandlerCompiler(isolate, Code::STORE_IC, type, holder,
    199                                 kCacheOnReceiver) {}
    200 
    201   virtual ~NamedStoreHandlerCompiler() {}
    202 
    203   Handle<Code> CompileStoreTransition(Handle<Map> transition,
    204                                       Handle<Name> name);
    205   Handle<Code> CompileStoreField(LookupIterator* it);
    206   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
    207                                     Handle<ExecutableAccessorInfo> callback);
    208   Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Name> name,
    209                                     const CallOptimization& call_optimization);
    210   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, Handle<Name> name,
    211                                      Handle<JSFunction> setter);
    212   Handle<Code> CompileStoreInterceptor(Handle<Name> name);
    213 
    214   static void GenerateStoreViaSetter(MacroAssembler* masm,
    215                                      Handle<HeapType> type, Register receiver,
    216                                      Handle<JSFunction> setter);
    217 
    218   static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
    219     GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg,
    220                            Handle<JSFunction>());
    221   }
    222 
    223   static void GenerateSlow(MacroAssembler* masm);
    224 
    225  protected:
    226   virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
    227                                   Label* miss);
    228 
    229   virtual void FrontendFooter(Handle<Name> name, Label* miss);
    230   void GenerateRestoreName(Label* label, Handle<Name> name);
    231 
    232  private:
    233   void GenerateStoreTransition(Handle<Map> transition, Handle<Name> name,
    234                                Register receiver_reg, Register name_reg,
    235                                Register value_reg, Register scratch1,
    236                                Register scratch2, Register scratch3,
    237                                Label* miss_label, Label* slow);
    238 
    239   void GenerateStoreField(LookupIterator* lookup, Register value_reg,
    240                           Label* miss_label);
    241 
    242   static Builtins::Name SlowBuiltin(Code::Kind kind) {
    243     switch (kind) {
    244       case Code::STORE_IC:
    245         return Builtins::kStoreIC_Slow;
    246       case Code::KEYED_STORE_IC:
    247         return Builtins::kKeyedStoreIC_Slow;
    248       default:
    249         UNREACHABLE();
    250     }
    251     return Builtins::kStoreIC_Slow;
    252   }
    253 
    254   static Register value();
    255 };
    256 
    257 
    258 class ElementHandlerCompiler : public PropertyHandlerCompiler {
    259  public:
    260   explicit ElementHandlerCompiler(Isolate* isolate)
    261       : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
    262                                 Handle<HeapType>::null(),
    263                                 Handle<JSObject>::null(), kCacheOnReceiver) {}
    264 
    265   virtual ~ElementHandlerCompiler() {}
    266 
    267   void CompileElementHandlers(MapHandleList* receiver_maps,
    268                               CodeHandleList* handlers);
    269 
    270   static void GenerateStoreSlow(MacroAssembler* masm);
    271 };
    272 }
    273 }  // namespace v8::internal
    274 
    275 #endif  // V8_IC_HANDLER_COMPILER_H_
    276