Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_STUB_CACHE_H_
     29 #define V8_STUB_CACHE_H_
     30 
     31 #include "allocation.h"
     32 #include "arguments.h"
     33 #include "code-stubs.h"
     34 #include "ic-inl.h"
     35 #include "macro-assembler.h"
     36 #include "objects.h"
     37 #include "zone-inl.h"
     38 
     39 namespace v8 {
     40 namespace internal {
     41 
     42 
     43 // The stub cache is used for megamorphic calls and property accesses.
     44 // It maps (map, name, type)->Code*
     45 
     46 // The design of the table uses the inline cache stubs used for
     47 // mono-morphic calls. The beauty of this, we do not have to
     48 // invalidate the cache whenever a prototype map is changed.  The stub
     49 // validates the map chain as in the mono-morphic case.
     50 
     51 class SmallMapList;
     52 class StubCache;
     53 
     54 
     55 class SCTableReference {
     56  public:
     57   Address address() const { return address_; }
     58 
     59  private:
     60   explicit SCTableReference(Address address) : address_(address) {}
     61 
     62   Address address_;
     63 
     64   friend class StubCache;
     65 };
     66 
     67 
     68 class StubCache {
     69  public:
     70   struct Entry {
     71     Name* key;
     72     Code* value;
     73     Map* map;
     74   };
     75 
     76   void Initialize();
     77 
     78   Handle<JSObject> StubHolder(Handle<JSObject> receiver,
     79                               Handle<JSObject> holder);
     80 
     81   Handle<Code> FindIC(Handle<Name> name,
     82                       Handle<Map> stub_holder_map,
     83                       Code::Kind kind,
     84                       Code::StubType type,
     85                       Code::ExtraICState extra_state = Code::kNoExtraICState);
     86 
     87   Handle<Code> FindIC(Handle<Name> name,
     88                       Handle<JSObject> stub_holder,
     89                       Code::Kind kind,
     90                       Code::StubType type,
     91                       Code::ExtraICState extra_state = Code::kNoExtraICState);
     92 
     93   Handle<Code> FindLoadHandler(Handle<Name> name,
     94                                Handle<JSObject> receiver,
     95                                Handle<JSObject> stub_holder,
     96                                Code::Kind kind,
     97                                Code::StubType type);
     98 
     99   Handle<Code> FindStoreHandler(Handle<Name> name,
    100                                 Handle<JSObject> receiver,
    101                                 Code::Kind kind,
    102                                 Code::StubType type,
    103                                 StrictModeFlag strict_mode);
    104 
    105   Handle<Code> ComputeMonomorphicLoadIC(Handle<JSObject> receiver,
    106                                         Handle<Code> handler,
    107                                         Handle<Name> name);
    108 
    109   Handle<Code> ComputeMonomorphicKeyedLoadIC(Handle<JSObject> receiver,
    110                                              Handle<Code> handler,
    111                                              Handle<Name> name);
    112 
    113   Handle<Code> ComputeMonomorphicStoreIC(Handle<JSObject> receiver,
    114                                          Handle<Code> handler,
    115                                          Handle<Name> name,
    116                                          StrictModeFlag strict_mode);
    117 
    118   Handle<Code> ComputeMonomorphicKeyedStoreIC(Handle<JSObject> receiver,
    119                                               Handle<Code> handler,
    120                                               Handle<Name> name,
    121                                               StrictModeFlag strict_mode);
    122 
    123   // Computes the right stub matching. Inserts the result in the
    124   // cache before returning.  This might compile a stub if needed.
    125   Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
    126                                       Handle<JSObject> object);
    127 
    128   Handle<Code> ComputeLoadField(Handle<Name> name,
    129                                 Handle<JSObject> object,
    130                                 Handle<JSObject> holder,
    131                                 PropertyIndex field_index,
    132                                 Representation representation);
    133 
    134   Handle<Code> ComputeLoadCallback(Handle<Name> name,
    135                                    Handle<JSObject> object,
    136                                    Handle<JSObject> holder,
    137                                    Handle<ExecutableAccessorInfo> callback);
    138 
    139   Handle<Code> ComputeLoadViaGetter(Handle<Name> name,
    140                                     Handle<JSObject> object,
    141                                     Handle<JSObject> holder,
    142                                     Handle<JSFunction> getter);
    143 
    144   Handle<Code> ComputeLoadConstant(Handle<Name> name,
    145                                    Handle<JSObject> object,
    146                                    Handle<JSObject> holder,
    147                                    Handle<Object> value);
    148 
    149   Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
    150                                       Handle<JSObject> object,
    151                                       Handle<JSObject> holder);
    152 
    153   Handle<Code> ComputeLoadNormal(Handle<Name> name,
    154                                  Handle<JSObject> object);
    155 
    156   Handle<Code> ComputeLoadGlobal(Handle<Name> name,
    157                                  Handle<JSObject> object,
    158                                  Handle<GlobalObject> holder,
    159                                  Handle<PropertyCell> cell,
    160                                  bool is_dont_delete);
    161 
    162   // ---
    163 
    164   Handle<Code> ComputeKeyedLoadField(Handle<Name> name,
    165                                      Handle<JSObject> object,
    166                                      Handle<JSObject> holder,
    167                                      PropertyIndex field_index,
    168                                      Representation representation);
    169 
    170   Handle<Code> ComputeKeyedLoadCallback(
    171       Handle<Name> name,
    172       Handle<JSObject> object,
    173       Handle<JSObject> holder,
    174       Handle<ExecutableAccessorInfo> callback);
    175 
    176   Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name,
    177                                         Handle<JSObject> object,
    178                                         Handle<JSObject> holder,
    179                                         Handle<Object> value);
    180 
    181   Handle<Code> ComputeKeyedLoadInterceptor(Handle<Name> name,
    182                                            Handle<JSObject> object,
    183                                            Handle<JSObject> holder);
    184 
    185   // ---
    186 
    187   Handle<Code> ComputeStoreField(Handle<Name> name,
    188                                  Handle<JSObject> object,
    189                                  LookupResult* lookup,
    190                                  StrictModeFlag strict_mode);
    191 
    192   Handle<Code> ComputeStoreTransition(Handle<Name> name,
    193                                       Handle<JSObject> object,
    194                                       LookupResult* lookup,
    195                                       Handle<Map> transition,
    196                                       StrictModeFlag strict_mode);
    197 
    198   Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
    199 
    200   Handle<Code> ComputeStoreGlobal(Handle<Name> name,
    201                                   Handle<GlobalObject> object,
    202                                   Handle<PropertyCell> cell,
    203                                   Handle<Object> value,
    204                                   StrictModeFlag strict_mode);
    205 
    206   Handle<Code> ComputeStoreCallback(Handle<Name> name,
    207                                     Handle<JSObject> object,
    208                                     Handle<JSObject> holder,
    209                                     Handle<ExecutableAccessorInfo> callback,
    210                                     StrictModeFlag strict_mode);
    211 
    212   Handle<Code> ComputeStoreViaSetter(Handle<Name> name,
    213                                      Handle<JSObject> object,
    214                                      Handle<JSObject> holder,
    215                                      Handle<JSFunction> setter,
    216                                      StrictModeFlag strict_mode);
    217 
    218   Handle<Code> ComputeStoreInterceptor(Handle<Name> name,
    219                                        Handle<JSObject> object,
    220                                        StrictModeFlag strict_mode);
    221 
    222   // ---
    223 
    224   Handle<Code> ComputeKeyedStoreField(Handle<Name> name,
    225                                       Handle<JSObject> object,
    226                                       LookupResult* lookup,
    227                                       StrictModeFlag strict_mode);
    228   Handle<Code> ComputeKeyedStoreTransition(Handle<Name> name,
    229                                            Handle<JSObject> object,
    230                                            LookupResult* lookup,
    231                                            Handle<Map> transition,
    232                                            StrictModeFlag strict_mode);
    233 
    234   Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
    235 
    236   Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
    237                                         StrictModeFlag strict_mode,
    238                                         KeyedAccessStoreMode store_mode);
    239 
    240   // ---
    241 
    242   Handle<Code> ComputeCallField(int argc,
    243                                 Code::Kind,
    244                                 Code::ExtraICState extra_state,
    245                                 Handle<Name> name,
    246                                 Handle<Object> object,
    247                                 Handle<JSObject> holder,
    248                                 PropertyIndex index);
    249 
    250   Handle<Code> ComputeCallConstant(int argc,
    251                                    Code::Kind,
    252                                    Code::ExtraICState extra_state,
    253                                    Handle<Name> name,
    254                                    Handle<Object> object,
    255                                    Handle<JSObject> holder,
    256                                    Handle<JSFunction> function);
    257 
    258   Handle<Code> ComputeCallInterceptor(int argc,
    259                                       Code::Kind,
    260                                       Code::ExtraICState extra_state,
    261                                       Handle<Name> name,
    262                                       Handle<Object> object,
    263                                       Handle<JSObject> holder);
    264 
    265   Handle<Code> ComputeCallGlobal(int argc,
    266                                  Code::Kind,
    267                                  Code::ExtraICState extra_state,
    268                                  Handle<Name> name,
    269                                  Handle<JSObject> object,
    270                                  Handle<GlobalObject> holder,
    271                                  Handle<PropertyCell> cell,
    272                                  Handle<JSFunction> function);
    273 
    274   // ---
    275 
    276   Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
    277 
    278   Handle<Code> ComputeKeyedCallInitialize(int argc);
    279 
    280   Handle<Code> ComputeCallPreMonomorphic(int argc,
    281                                          Code::Kind kind,
    282                                          Code::ExtraICState extra_state);
    283 
    284   Handle<Code> ComputeCallNormal(int argc,
    285                                  Code::Kind kind,
    286                                  Code::ExtraICState state);
    287 
    288   Handle<Code> ComputeCallArguments(int argc);
    289 
    290   Handle<Code> ComputeCallMegamorphic(int argc,
    291                                       Code::Kind kind,
    292                                       Code::ExtraICState state);
    293 
    294   Handle<Code> ComputeCallMiss(int argc,
    295                                Code::Kind kind,
    296                                Code::ExtraICState state);
    297 
    298   // ---
    299 
    300   Handle<Code> ComputeCompareNil(Handle<Map> receiver_map,
    301                                  CompareNilICStub& stub);
    302 
    303   // ---
    304 
    305   Handle<Code> ComputeLoadElementPolymorphic(MapHandleList* receiver_maps);
    306   Handle<Code> ComputeStoreElementPolymorphic(MapHandleList* receiver_maps,
    307                                               KeyedAccessStoreMode store_mode,
    308                                               StrictModeFlag strict_mode);
    309 
    310   Handle<Code> ComputePolymorphicLoadIC(MapHandleList* receiver_maps,
    311                                         CodeHandleList* handlers,
    312                                         int number_of_valid_maps,
    313                                         Handle<Name> name);
    314 
    315   Handle<Code> ComputePolymorphicStoreIC(MapHandleList* receiver_maps,
    316                                          CodeHandleList* handlers,
    317                                          int number_of_valid_maps,
    318                                          Handle<Name> name,
    319                                          StrictModeFlag strict_mode);
    320 
    321   // Finds the Code object stored in the Heap::non_monomorphic_cache().
    322   Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
    323 
    324 #ifdef ENABLE_DEBUGGER_SUPPORT
    325   Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
    326 
    327   Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
    328 #endif
    329 
    330   // Update cache for entry hash(name, map).
    331   Code* Set(Name* name, Map* map, Code* code);
    332 
    333   // Clear the lookup table (@ mark compact collection).
    334   void Clear();
    335 
    336   // Collect all maps that match the name and flags.
    337   void CollectMatchingMaps(SmallMapList* types,
    338                            Handle<Name> name,
    339                            Code::Flags flags,
    340                            Handle<Context> native_context,
    341                            Zone* zone);
    342 
    343   // Generate code for probing the stub cache table.
    344   // Arguments extra, extra2 and extra3 may be used to pass additional scratch
    345   // registers. Set to no_reg if not needed.
    346   void GenerateProbe(MacroAssembler* masm,
    347                      Code::Flags flags,
    348                      Register receiver,
    349                      Register name,
    350                      Register scratch,
    351                      Register extra,
    352                      Register extra2 = no_reg,
    353                      Register extra3 = no_reg);
    354 
    355   enum Table {
    356     kPrimary,
    357     kSecondary
    358   };
    359 
    360 
    361   SCTableReference key_reference(StubCache::Table table) {
    362     return SCTableReference(
    363         reinterpret_cast<Address>(&first_entry(table)->key));
    364   }
    365 
    366 
    367   SCTableReference map_reference(StubCache::Table table) {
    368     return SCTableReference(
    369         reinterpret_cast<Address>(&first_entry(table)->map));
    370   }
    371 
    372 
    373   SCTableReference value_reference(StubCache::Table table) {
    374     return SCTableReference(
    375         reinterpret_cast<Address>(&first_entry(table)->value));
    376   }
    377 
    378 
    379   StubCache::Entry* first_entry(StubCache::Table table) {
    380     switch (table) {
    381       case StubCache::kPrimary: return StubCache::primary_;
    382       case StubCache::kSecondary: return StubCache::secondary_;
    383     }
    384     UNREACHABLE();
    385     return NULL;
    386   }
    387 
    388   Isolate* isolate() { return isolate_; }
    389   Heap* heap() { return isolate()->heap(); }
    390   Factory* factory() { return isolate()->factory(); }
    391 
    392  private:
    393   explicit StubCache(Isolate* isolate);
    394 
    395   Handle<Code> ComputeCallInitialize(int argc,
    396                                      RelocInfo::Mode mode,
    397                                      Code::Kind kind);
    398 
    399   // The stub cache has a primary and secondary level.  The two levels have
    400   // different hashing algorithms in order to avoid simultaneous collisions
    401   // in both caches.  Unlike a probing strategy (quadratic or otherwise) the
    402   // update strategy on updates is fairly clear and simple:  Any existing entry
    403   // in the primary cache is moved to the secondary cache, and secondary cache
    404   // entries are overwritten.
    405 
    406   // Hash algorithm for the primary table.  This algorithm is replicated in
    407   // assembler for every architecture.  Returns an index into the table that
    408   // is scaled by 1 << kHeapObjectTagSize.
    409   static int PrimaryOffset(Name* name, Code::Flags flags, Map* map) {
    410     // This works well because the heap object tag size and the hash
    411     // shift are equal.  Shifting down the length field to get the
    412     // hash code would effectively throw away two bits of the hash
    413     // code.
    414     STATIC_ASSERT(kHeapObjectTagSize == Name::kHashShift);
    415     // Compute the hash of the name (use entire hash field).
    416     ASSERT(name->HasHashCode());
    417     uint32_t field = name->hash_field();
    418     // Using only the low bits in 64-bit mode is unlikely to increase the
    419     // risk of collision even if the heap is spread over an area larger than
    420     // 4Gb (and not at all if it isn't).
    421     uint32_t map_low32bits =
    422         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
    423     // We always set the in_loop bit to zero when generating the lookup code
    424     // so do it here too so the hash codes match.
    425     uint32_t iflags =
    426         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
    427     // Base the offset on a simple combination of name, flags, and map.
    428     uint32_t key = (map_low32bits + field) ^ iflags;
    429     return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
    430   }
    431 
    432   // Hash algorithm for the secondary table.  This algorithm is replicated in
    433   // assembler for every architecture.  Returns an index into the table that
    434   // is scaled by 1 << kHeapObjectTagSize.
    435   static int SecondaryOffset(Name* name, Code::Flags flags, int seed) {
    436     // Use the seed from the primary cache in the secondary cache.
    437     uint32_t name_low32bits =
    438         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
    439     // We always set the in_loop bit to zero when generating the lookup code
    440     // so do it here too so the hash codes match.
    441     uint32_t iflags =
    442         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
    443     uint32_t key = (seed - name_low32bits) + iflags;
    444     return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
    445   }
    446 
    447   // Compute the entry for a given offset in exactly the same way as
    448   // we do in generated code.  We generate an hash code that already
    449   // ends in Name::kHashShift 0s.  Then we multiply it so it is a multiple
    450   // of sizeof(Entry).  This makes it easier to avoid making mistakes
    451   // in the hashed offset computations.
    452   static Entry* entry(Entry* table, int offset) {
    453     const int multiplier = sizeof(*table) >> Name::kHashShift;
    454     return reinterpret_cast<Entry*>(
    455         reinterpret_cast<Address>(table) + offset * multiplier);
    456   }
    457 
    458   static const int kPrimaryTableBits = 11;
    459   static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
    460   static const int kSecondaryTableBits = 9;
    461   static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
    462 
    463   Entry primary_[kPrimaryTableSize];
    464   Entry secondary_[kSecondaryTableSize];
    465   Isolate* isolate_;
    466 
    467   friend class Isolate;
    468   friend class SCTableReference;
    469 
    470   DISALLOW_COPY_AND_ASSIGN(StubCache);
    471 };
    472 
    473 
    474 // ------------------------------------------------------------------------
    475 
    476 
    477 // Support functions for IC stubs for callbacks.
    478 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
    479 
    480 
    481 // Support functions for IC stubs for interceptors.
    482 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
    483 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
    484 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
    485 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
    486 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
    487 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
    488 
    489 
    490 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
    491 enum IcCheckType { ELEMENT, PROPERTY };
    492 
    493 
    494 // The stub compilers compile stubs for the stub cache.
    495 class StubCompiler BASE_EMBEDDED {
    496  public:
    497   explicit StubCompiler(Isolate* isolate)
    498       : isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
    499 
    500   // Functions to compile either CallIC or KeyedCallIC.  The specific kind
    501   // is extracted from the code flags.
    502   Handle<Code> CompileCallInitialize(Code::Flags flags);
    503   Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
    504   Handle<Code> CompileCallNormal(Code::Flags flags);
    505   Handle<Code> CompileCallMegamorphic(Code::Flags flags);
    506   Handle<Code> CompileCallArguments(Code::Flags flags);
    507   Handle<Code> CompileCallMiss(Code::Flags flags);
    508 
    509 #ifdef ENABLE_DEBUGGER_SUPPORT
    510   Handle<Code> CompileCallDebugBreak(Code::Flags flags);
    511   Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
    512 #endif
    513 
    514   // Static functions for generating parts of stubs.
    515   static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
    516                                                   int index,
    517                                                   Register prototype);
    518 
    519   // Generates prototype loading code that uses the objects from the
    520   // context we were in when this function was called. If the context
    521   // has changed, a jump to miss is performed. This ties the generated
    522   // code to a particular context and so must not be used in cases
    523   // where the generated code is not allowed to have references to
    524   // objects from a context.
    525   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
    526                                                         int index,
    527                                                         Register prototype,
    528                                                         Label* miss);
    529 
    530   static void GenerateFastPropertyLoad(MacroAssembler* masm,
    531                                        Register dst,
    532                                        Register src,
    533                                        bool inobject,
    534                                        int index,
    535                                        Representation representation);
    536 
    537   static void GenerateLoadArrayLength(MacroAssembler* masm,
    538                                       Register receiver,
    539                                       Register scratch,
    540                                       Label* miss_label);
    541 
    542   static void GenerateLoadStringLength(MacroAssembler* masm,
    543                                        Register receiver,
    544                                        Register scratch1,
    545                                        Register scratch2,
    546                                        Label* miss_label,
    547                                        bool support_wrappers);
    548 
    549   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
    550                                             Register receiver,
    551                                             Register scratch1,
    552                                             Register scratch2,
    553                                             Label* miss_label);
    554 
    555   static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
    556 
    557   // Generates code that verifies that the property holder has not changed
    558   // (checking maps of objects in the prototype chain for fast and global
    559   // objects or doing negative lookup for slow objects, ensures that the
    560   // property cells for global objects are still empty) and checks that the map
    561   // of the holder has not changed. If necessary the function also generates
    562   // code for security check in case of global object holders. Helps to make
    563   // sure that the current IC is still valid.
    564   //
    565   // The scratch and holder registers are always clobbered, but the object
    566   // register is only clobbered if it the same as the holder register. The
    567   // function returns a register containing the holder - either object_reg or
    568   // holder_reg.
    569   // The function can optionally (when save_at_depth !=
    570   // kInvalidProtoDepth) save the object at the given depth by moving
    571   // it to [esp + kPointerSize].
    572   Register CheckPrototypes(Handle<JSObject> object,
    573                            Register object_reg,
    574                            Handle<JSObject> holder,
    575                            Register holder_reg,
    576                            Register scratch1,
    577                            Register scratch2,
    578                            Handle<Name> name,
    579                            Label* miss,
    580                            PrototypeCheckType check = CHECK_ALL_MAPS) {
    581     return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
    582                            scratch2, name, kInvalidProtoDepth, miss, check);
    583   }
    584 
    585   Register CheckPrototypes(Handle<JSObject> object,
    586                            Register object_reg,
    587                            Handle<JSObject> holder,
    588                            Register holder_reg,
    589                            Register scratch1,
    590                            Register scratch2,
    591                            Handle<Name> name,
    592                            int save_at_depth,
    593                            Label* miss,
    594                            PrototypeCheckType check = CHECK_ALL_MAPS);
    595 
    596 
    597  protected:
    598   Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
    599   Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
    600 
    601   MacroAssembler* masm() { return &masm_; }
    602   void set_failure(Failure* failure) { failure_ = failure; }
    603 
    604   static void LookupPostInterceptor(Handle<JSObject> holder,
    605                                     Handle<Name> name,
    606                                     LookupResult* lookup);
    607 
    608   Isolate* isolate() { return isolate_; }
    609   Heap* heap() { return isolate()->heap(); }
    610   Factory* factory() { return isolate()->factory(); }
    611 
    612   static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
    613 
    614  private:
    615   Isolate* isolate_;
    616   MacroAssembler masm_;
    617   Failure* failure_;
    618 };
    619 
    620 
    621 enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
    622 
    623 
    624 class BaseLoadStoreStubCompiler: public StubCompiler {
    625  public:
    626   BaseLoadStoreStubCompiler(Isolate* isolate, Register* registers)
    627       : StubCompiler(isolate), registers_(registers) { }
    628   virtual ~BaseLoadStoreStubCompiler() { }
    629 
    630   Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
    631                                     Handle<Code> handler,
    632                                     Handle<Name> name);
    633 
    634   Handle<Code> CompilePolymorphicIC(MapHandleList* receiver_maps,
    635                                     CodeHandleList* handlers,
    636                                     Handle<Name> name,
    637                                     Code::StubType type,
    638                                     IcCheckType check);
    639 
    640   virtual void GenerateNameCheck(Handle<Name> name,
    641                                  Register name_reg,
    642                                  Label* miss) { }
    643 
    644   static Builtins::Name MissBuiltin(Code::Kind kind) {
    645     switch (kind) {
    646       case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
    647       case Code::STORE_IC: return Builtins::kStoreIC_Miss;
    648       case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
    649       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
    650       default: UNREACHABLE();
    651     }
    652     return Builtins::kLoadIC_Miss;
    653   }
    654 
    655  protected:
    656   virtual Register HandlerFrontendHeader(Handle<JSObject> object,
    657                                          Register object_reg,
    658                                          Handle<JSObject> holder,
    659                                          Handle<Name> name,
    660                                          Label* miss) = 0;
    661 
    662   virtual void HandlerFrontendFooter(Handle<Name> name,
    663                                      Label* success,
    664                                      Label* miss) = 0;
    665 
    666   Register HandlerFrontend(Handle<JSObject> object,
    667                            Register object_reg,
    668                            Handle<JSObject> holder,
    669                            Handle<Name> name,
    670                            Label* success);
    671 
    672   Handle<Code> GetICCode(Code::Kind kind,
    673                          Code::StubType type,
    674                          Handle<Name> name,
    675                          InlineCacheState state = MONOMORPHIC);
    676 
    677   virtual Code::ExtraICState extra_state() { return Code::kNoExtraICState; }
    678   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
    679   virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
    680   virtual Code::Kind kind() = 0;
    681   virtual Register receiver() = 0;
    682   virtual Register name() = 0;
    683   virtual Register scratch1() = 0;
    684   virtual Register scratch2() = 0;
    685   virtual Register scratch3() = 0;
    686 
    687   Register* registers_;
    688 };
    689 
    690 
    691 class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
    692  public:
    693   BaseLoadStubCompiler(Isolate* isolate, Register* registers)
    694       : BaseLoadStoreStubCompiler(isolate, registers) { }
    695   virtual ~BaseLoadStubCompiler() { }
    696 
    697   Handle<Code> CompileLoadField(Handle<JSObject> object,
    698                                 Handle<JSObject> holder,
    699                                 Handle<Name> name,
    700                                 PropertyIndex index,
    701                                 Representation representation);
    702 
    703   Handle<Code> CompileLoadCallback(Handle<JSObject> object,
    704                                    Handle<JSObject> holder,
    705                                    Handle<Name> name,
    706                                    Handle<ExecutableAccessorInfo> callback);
    707 
    708   Handle<Code> CompileLoadConstant(Handle<JSObject> object,
    709                                    Handle<JSObject> holder,
    710                                    Handle<Name> name,
    711                                    Handle<Object> value);
    712 
    713   Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
    714                                       Handle<JSObject> holder,
    715                                       Handle<Name> name);
    716 
    717  protected:
    718   virtual Register HandlerFrontendHeader(Handle<JSObject> object,
    719                                          Register object_reg,
    720                                          Handle<JSObject> holder,
    721                                          Handle<Name> name,
    722                                          Label* miss);
    723 
    724   virtual void HandlerFrontendFooter(Handle<Name> name,
    725                                      Label* success,
    726                                      Label* miss);
    727 
    728   Register CallbackHandlerFrontend(Handle<JSObject> object,
    729                                    Register object_reg,
    730                                    Handle<JSObject> holder,
    731                                    Handle<Name> name,
    732                                    Label* success,
    733                                    Handle<ExecutableAccessorInfo> callback);
    734   void NonexistentHandlerFrontend(Handle<JSObject> object,
    735                                   Handle<JSObject> last,
    736                                   Handle<Name> name,
    737                                   Label* success,
    738                                   Handle<GlobalObject> global);
    739 
    740   void GenerateLoadField(Register reg,
    741                          Handle<JSObject> holder,
    742                          PropertyIndex field,
    743                          Representation representation);
    744   void GenerateLoadConstant(Handle<Object> value);
    745   void GenerateLoadCallback(Register reg,
    746                             Handle<ExecutableAccessorInfo> callback);
    747   void GenerateLoadInterceptor(Register holder_reg,
    748                                Handle<JSObject> object,
    749                                Handle<JSObject> holder,
    750                                LookupResult* lookup,
    751                                Handle<Name> name);
    752   void GenerateLoadPostInterceptor(Register reg,
    753                                    Handle<JSObject> interceptor_holder,
    754                                    Handle<Name> name,
    755                                    LookupResult* lookup);
    756 
    757   Handle<Code> GetCode(Code::Kind kind,
    758                        Code::StubType type,
    759                        Handle<Name> name);
    760 
    761   virtual Register receiver() { return registers_[0]; }
    762   virtual Register name()     { return registers_[1]; }
    763   virtual Register scratch1() { return registers_[2]; }
    764   virtual Register scratch2() { return registers_[3]; }
    765   virtual Register scratch3() { return registers_[4]; }
    766   Register scratch4() { return registers_[5]; }
    767 };
    768 
    769 
    770 class LoadStubCompiler: public BaseLoadStubCompiler {
    771  public:
    772   explicit LoadStubCompiler(Isolate* isolate)
    773       : BaseLoadStubCompiler(isolate, registers()) { }
    774 
    775   Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
    776                                       Handle<JSObject> last,
    777                                       Handle<Name> name,
    778                                       Handle<GlobalObject> global);
    779 
    780   static void GenerateLoadViaGetter(MacroAssembler* masm,
    781                                     Handle<JSFunction> getter);
    782 
    783   Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
    784                                     Handle<JSObject> holder,
    785                                     Handle<Name> name,
    786                                     Handle<JSFunction> getter);
    787 
    788   Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
    789                                  Handle<GlobalObject> holder,
    790                                  Handle<PropertyCell> cell,
    791                                  Handle<Name> name,
    792                                  bool is_dont_delete);
    793 
    794  private:
    795   static Register* registers();
    796   virtual Code::Kind kind() { return Code::LOAD_IC; }
    797   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
    798     if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
    799     return code->ic_state() == MONOMORPHIC
    800         ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
    801   }
    802   virtual void JitEvent(Handle<Name> name, Handle<Code> code);
    803 };
    804 
    805 
    806 class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
    807  public:
    808   explicit KeyedLoadStubCompiler(Isolate* isolate)
    809       : BaseLoadStubCompiler(isolate, registers()) { }
    810 
    811   Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
    812 
    813   void CompileElementHandlers(MapHandleList* receiver_maps,
    814                               CodeHandleList* handlers);
    815 
    816   static void GenerateLoadDictionaryElement(MacroAssembler* masm);
    817 
    818  private:
    819   static Register* registers();
    820   virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
    821   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
    822     if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
    823     return code->ic_state() == MONOMORPHIC
    824         ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
    825   }
    826   virtual void JitEvent(Handle<Name> name, Handle<Code> code);
    827   virtual void GenerateNameCheck(Handle<Name> name,
    828                                  Register name_reg,
    829                                  Label* miss);
    830 };
    831 
    832 
    833 class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
    834  public:
    835   BaseStoreStubCompiler(Isolate* isolate,
    836                         StrictModeFlag strict_mode,
    837                         Register* registers)
    838       : BaseLoadStoreStubCompiler(isolate, registers),
    839         strict_mode_(strict_mode) { }
    840 
    841   virtual ~BaseStoreStubCompiler() { }
    842 
    843   Handle<Code> CompileStoreTransition(Handle<JSObject> object,
    844                                       LookupResult* lookup,
    845                                       Handle<Map> transition,
    846                                       Handle<Name> name);
    847 
    848   Handle<Code> CompileStoreField(Handle<JSObject> object,
    849                                  LookupResult* lookup,
    850                                  Handle<Name> name);
    851 
    852   void GenerateNegativeHolderLookup(MacroAssembler* masm,
    853                                     Handle<JSObject> holder,
    854                                     Register holder_reg,
    855                                     Handle<Name> name,
    856                                     Label* miss);
    857 
    858   void GenerateStoreTransition(MacroAssembler* masm,
    859                                Handle<JSObject> object,
    860                                LookupResult* lookup,
    861                                Handle<Map> transition,
    862                                Handle<Name> name,
    863                                Register receiver_reg,
    864                                Register name_reg,
    865                                Register value_reg,
    866                                Register scratch1,
    867                                Register scratch2,
    868                                Register scratch3,
    869                                Label* miss_label,
    870                                Label* slow);
    871 
    872   void GenerateStoreField(MacroAssembler* masm,
    873                           Handle<JSObject> object,
    874                           LookupResult* lookup,
    875                           Register receiver_reg,
    876                           Register name_reg,
    877                           Register value_reg,
    878                           Register scratch1,
    879                           Register scratch2,
    880                           Label* miss_label);
    881 
    882   static Builtins::Name MissBuiltin(Code::Kind kind) {
    883     switch (kind) {
    884       case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
    885       case Code::STORE_IC: return Builtins::kStoreIC_Miss;
    886       case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
    887       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
    888       default: UNREACHABLE();
    889     }
    890     return Builtins::kLoadIC_Miss;
    891   }
    892   static Builtins::Name SlowBuiltin(Code::Kind kind) {
    893     switch (kind) {
    894       case Code::STORE_IC: return Builtins::kStoreIC_Slow;
    895       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow;
    896       default: UNREACHABLE();
    897     }
    898     return Builtins::kStoreIC_Slow;
    899   }
    900 
    901  protected:
    902   virtual Register HandlerFrontendHeader(Handle<JSObject> object,
    903                                          Register object_reg,
    904                                          Handle<JSObject> holder,
    905                                          Handle<Name> name,
    906                                          Label* miss);
    907 
    908   virtual void HandlerFrontendFooter(Handle<Name> name,
    909                                      Label* success,
    910                                      Label* miss);
    911   Handle<Code> GetCode(Code::Kind kind,
    912                        Code::StubType type,
    913                        Handle<Name> name);
    914 
    915   void GenerateRestoreName(MacroAssembler* masm,
    916                            Label* label,
    917                            Handle<Name> name);
    918 
    919   virtual Register receiver() { return registers_[0]; }
    920   virtual Register name()     { return registers_[1]; }
    921   Register value()    { return registers_[2]; }
    922   virtual Register scratch1() { return registers_[3]; }
    923   virtual Register scratch2() { return registers_[4]; }
    924   virtual Register scratch3() { return registers_[5]; }
    925   StrictModeFlag strict_mode() { return strict_mode_; }
    926   virtual Code::ExtraICState extra_state() { return strict_mode_; }
    927 
    928  private:
    929   StrictModeFlag strict_mode_;
    930 };
    931 
    932 
    933 class StoreStubCompiler: public BaseStoreStubCompiler {
    934  public:
    935   StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
    936       : BaseStoreStubCompiler(isolate, strict_mode, registers()) { }
    937 
    938 
    939   Handle<Code> CompileStoreCallback(Handle<JSObject> object,
    940                                     Handle<JSObject> holder,
    941                                     Handle<Name> name,
    942                                     Handle<ExecutableAccessorInfo> callback);
    943 
    944   static void GenerateStoreViaSetter(MacroAssembler* masm,
    945                                      Handle<JSFunction> setter);
    946 
    947   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object,
    948                                      Handle<JSObject> holder,
    949                                      Handle<Name> name,
    950                                      Handle<JSFunction> setter);
    951 
    952   Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
    953                                        Handle<Name> name);
    954 
    955   Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
    956                                   Handle<PropertyCell> holder,
    957                                   Handle<Name> name);
    958 
    959  private:
    960   static Register* registers();
    961   virtual Code::Kind kind() { return Code::STORE_IC; }
    962   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
    963     if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
    964     return code->ic_state() == MONOMORPHIC
    965         ? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
    966   }
    967   virtual void JitEvent(Handle<Name> name, Handle<Code> code);
    968 };
    969 
    970 
    971 class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
    972  public:
    973   KeyedStoreStubCompiler(Isolate* isolate,
    974                          StrictModeFlag strict_mode,
    975                          KeyedAccessStoreMode store_mode)
    976       : BaseStoreStubCompiler(isolate, strict_mode, registers()),
    977         store_mode_(store_mode) { }
    978 
    979   Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
    980 
    981   Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
    982                                        CodeHandleList* handler_stubs,
    983                                        MapHandleList* transitioned_maps);
    984 
    985   Handle<Code> CompileStoreElementPolymorphic(MapHandleList* receiver_maps);
    986 
    987   static void GenerateStoreFastElement(MacroAssembler* masm,
    988                                        bool is_js_array,
    989                                        ElementsKind element_kind,
    990                                        KeyedAccessStoreMode store_mode);
    991 
    992   static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
    993                                              bool is_js_array,
    994                                              KeyedAccessStoreMode store_mode);
    995 
    996   static void GenerateStoreExternalArray(MacroAssembler* masm,
    997                                          ElementsKind elements_kind);
    998 
    999   static void GenerateStoreDictionaryElement(MacroAssembler* masm);
   1000 
   1001  protected:
   1002   virtual Code::ExtraICState extra_state() {
   1003     return Code::ComputeExtraICState(store_mode_, strict_mode());
   1004   }
   1005 
   1006  private:
   1007   Register transition_map() {
   1008     return registers()[3];
   1009   }
   1010 
   1011   static Register* registers();
   1012   virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
   1013   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
   1014     if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
   1015     return code->ic_state() == MONOMORPHIC
   1016         ? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
   1017   }
   1018   virtual void JitEvent(Handle<Name> name, Handle<Code> code);
   1019   virtual void GenerateNameCheck(Handle<Name> name,
   1020                                  Register name_reg,
   1021                                  Label* miss);
   1022   KeyedAccessStoreMode store_mode_;
   1023 };
   1024 
   1025 
   1026 // Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
   1027 // IC stubs.
   1028 #define CUSTOM_CALL_IC_GENERATORS(V)            \
   1029   V(ArrayPush)                                  \
   1030   V(ArrayPop)                                   \
   1031   V(StringCharCodeAt)                           \
   1032   V(StringCharAt)                               \
   1033   V(StringFromCharCode)                         \
   1034   V(MathFloor)                                  \
   1035   V(MathAbs)                                    \
   1036   V(ArrayCode)
   1037 
   1038 
   1039 #define SITE_SPECIFIC_CALL_GENERATORS(V)        \
   1040   V(ArrayCode)
   1041 
   1042 
   1043 class CallOptimization;
   1044 
   1045 class CallStubCompiler: public StubCompiler {
   1046  public:
   1047   CallStubCompiler(Isolate* isolate,
   1048                    int argc,
   1049                    Code::Kind kind,
   1050                    Code::ExtraICState extra_state,
   1051                    InlineCacheHolderFlag cache_holder);
   1052 
   1053   Handle<Code> CompileCallField(Handle<JSObject> object,
   1054                                 Handle<JSObject> holder,
   1055                                 PropertyIndex index,
   1056                                 Handle<Name> name);
   1057 
   1058   void CompileHandlerFrontend(Handle<Object> object,
   1059                               Handle<JSObject> holder,
   1060                               Handle<Name> name,
   1061                               CheckType check,
   1062                               Label* success);
   1063 
   1064   void CompileHandlerBackend(Handle<JSFunction> function);
   1065 
   1066   Handle<Code> CompileCallConstant(Handle<Object> object,
   1067                                    Handle<JSObject> holder,
   1068                                    Handle<Name> name,
   1069                                    CheckType check,
   1070                                    Handle<JSFunction> function);
   1071 
   1072   Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
   1073                                       Handle<JSObject> holder,
   1074                                       Handle<Name> name);
   1075 
   1076   Handle<Code> CompileCallGlobal(Handle<JSObject> object,
   1077                                  Handle<GlobalObject> holder,
   1078                                  Handle<PropertyCell> cell,
   1079                                  Handle<JSFunction> function,
   1080                                  Handle<Name> name);
   1081 
   1082   static bool HasCustomCallGenerator(Handle<JSFunction> function);
   1083   static bool CanBeCached(Handle<JSFunction> function);
   1084 
   1085  private:
   1086   // Compiles a custom call constant/global IC.  For constant calls cell is
   1087   // NULL.  Returns an empty handle if there is no custom call code for the
   1088   // given function.
   1089   Handle<Code> CompileCustomCall(Handle<Object> object,
   1090                                  Handle<JSObject> holder,
   1091                                  Handle<Cell> cell,
   1092                                  Handle<JSFunction> function,
   1093                                  Handle<String> name,
   1094                                  Code::StubType type);
   1095 
   1096 #define DECLARE_CALL_GENERATOR(name)                                    \
   1097   Handle<Code> Compile##name##Call(Handle<Object> object,               \
   1098                                    Handle<JSObject> holder,             \
   1099                                    Handle<Cell> cell,                   \
   1100                                    Handle<JSFunction> function,         \
   1101                                    Handle<String> fname,                \
   1102                                    Code::StubType type);
   1103   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
   1104 #undef DECLARE_CALL_GENERATOR
   1105 
   1106   Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
   1107                                   Handle<Object> object,
   1108                                   Handle<JSObject> holder,
   1109                                   Handle<Cell> cell,
   1110                                   Handle<JSFunction> function,
   1111                                   Handle<String> name);
   1112 
   1113   Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
   1114   Handle<Code> GetCode(Handle<JSFunction> function);
   1115 
   1116   const ParameterCount& arguments() { return arguments_; }
   1117 
   1118   void GenerateNameCheck(Handle<Name> name, Label* miss);
   1119 
   1120   void GenerateGlobalReceiverCheck(Handle<JSObject> object,
   1121                                    Handle<JSObject> holder,
   1122                                    Handle<Name> name,
   1123                                    Label* miss);
   1124 
   1125   // Generates code to load the function from the cell checking that
   1126   // it still contains the same function.
   1127   void GenerateLoadFunctionFromCell(Handle<Cell> cell,
   1128                                     Handle<JSFunction> function,
   1129                                     Label* miss);
   1130 
   1131   // Generates a jump to CallIC miss stub.
   1132   void GenerateMissBranch();
   1133 
   1134   const ParameterCount arguments_;
   1135   const Code::Kind kind_;
   1136   const Code::ExtraICState extra_state_;
   1137   const InlineCacheHolderFlag cache_holder_;
   1138 };
   1139 
   1140 
   1141 // Holds information about possible function call optimizations.
   1142 class CallOptimization BASE_EMBEDDED {
   1143  public:
   1144   explicit CallOptimization(LookupResult* lookup);
   1145 
   1146   explicit CallOptimization(Handle<JSFunction> function);
   1147 
   1148   bool is_constant_call() const {
   1149     return !constant_function_.is_null();
   1150   }
   1151 
   1152   Handle<JSFunction> constant_function() const {
   1153     ASSERT(is_constant_call());
   1154     return constant_function_;
   1155   }
   1156 
   1157   bool is_simple_api_call() const {
   1158     return is_simple_api_call_;
   1159   }
   1160 
   1161   Handle<FunctionTemplateInfo> expected_receiver_type() const {
   1162     ASSERT(is_simple_api_call());
   1163     return expected_receiver_type_;
   1164   }
   1165 
   1166   Handle<CallHandlerInfo> api_call_info() const {
   1167     ASSERT(is_simple_api_call());
   1168     return api_call_info_;
   1169   }
   1170 
   1171   // Returns the depth of the object having the expected type in the
   1172   // prototype chain between the two arguments.
   1173   int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
   1174                                       Handle<JSObject> holder) const;
   1175 
   1176  private:
   1177   void Initialize(Handle<JSFunction> function);
   1178 
   1179   // Determines whether the given function can be called using the
   1180   // fast api call builtin.
   1181   void AnalyzePossibleApiFunction(Handle<JSFunction> function);
   1182 
   1183   Handle<JSFunction> constant_function_;
   1184   bool is_simple_api_call_;
   1185   Handle<FunctionTemplateInfo> expected_receiver_type_;
   1186   Handle<CallHandlerInfo> api_call_info_;
   1187 };
   1188 
   1189 
   1190 } }  // namespace v8::internal
   1191 
   1192 #endif  // V8_STUB_CACHE_H_
   1193