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 
     52 class CallOptimization;
     53 class SmallMapList;
     54 class StubCache;
     55 
     56 
     57 class SCTableReference {
     58  public:
     59   Address address() const { return address_; }
     60 
     61  private:
     62   explicit SCTableReference(Address address) : address_(address) {}
     63 
     64   Address address_;
     65 
     66   friend class StubCache;
     67 };
     68 
     69 
     70 class StubCache {
     71  public:
     72   struct Entry {
     73     Name* key;
     74     Code* value;
     75     Map* map;
     76   };
     77 
     78   void Initialize();
     79 
     80   Handle<JSObject> StubHolder(Handle<JSObject> receiver,
     81                               Handle<JSObject> holder);
     82 
     83   Handle<Code> FindIC(Handle<Name> name,
     84                       Handle<Map> stub_holder_map,
     85                       Code::Kind kind,
     86                       ExtraICState extra_state = kNoExtraICState,
     87                       InlineCacheHolderFlag cache_holder = OWN_MAP);
     88 
     89   Handle<Code> FindHandler(Handle<Name> name,
     90                            Handle<Map> map,
     91                            Code::Kind kind,
     92                            InlineCacheHolderFlag cache_holder = OWN_MAP);
     93 
     94   Handle<Code> ComputeMonomorphicIC(Handle<Name> name,
     95                                     Handle<Type> type,
     96                                     Handle<Code> handler,
     97                                     ExtraICState extra_ic_state);
     98 
     99   Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<Type> type);
    100 
    101   Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
    102 
    103   Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
    104                                         StrictModeFlag strict_mode,
    105                                         KeyedAccessStoreMode store_mode);
    106 
    107   Handle<Code> ComputeCallField(int argc,
    108                                 Code::Kind,
    109                                 ExtraICState extra_state,
    110                                 Handle<Name> name,
    111                                 Handle<Object> object,
    112                                 Handle<JSObject> holder,
    113                                 PropertyIndex index);
    114 
    115   Handle<Code> ComputeCallConstant(int argc,
    116                                    Code::Kind,
    117                                    ExtraICState extra_state,
    118                                    Handle<Name> name,
    119                                    Handle<Object> object,
    120                                    Handle<JSObject> holder,
    121                                    Handle<JSFunction> function);
    122 
    123   Handle<Code> ComputeCallInterceptor(int argc,
    124                                       Code::Kind,
    125                                       ExtraICState extra_state,
    126                                       Handle<Name> name,
    127                                       Handle<Object> object,
    128                                       Handle<JSObject> holder);
    129 
    130   Handle<Code> ComputeCallGlobal(int argc,
    131                                  Code::Kind,
    132                                  ExtraICState extra_state,
    133                                  Handle<Name> name,
    134                                  Handle<JSObject> object,
    135                                  Handle<GlobalObject> holder,
    136                                  Handle<PropertyCell> cell,
    137                                  Handle<JSFunction> function);
    138 
    139   // ---
    140 
    141   Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
    142 
    143   Handle<Code> ComputeKeyedCallInitialize(int argc);
    144 
    145   Handle<Code> ComputeCallPreMonomorphic(int argc,
    146                                          Code::Kind kind,
    147                                          ExtraICState extra_state);
    148 
    149   Handle<Code> ComputeCallNormal(int argc,
    150                                  Code::Kind kind,
    151                                  ExtraICState state);
    152 
    153   Handle<Code> ComputeCallArguments(int argc);
    154 
    155   Handle<Code> ComputeCallMegamorphic(int argc,
    156                                       Code::Kind kind,
    157                                       ExtraICState state);
    158 
    159   Handle<Code> ComputeCallMiss(int argc,
    160                                Code::Kind kind,
    161                                ExtraICState state);
    162 
    163   // ---
    164 
    165   Handle<Code> ComputeCompareNil(Handle<Map> receiver_map,
    166                                  CompareNilICStub& stub);
    167 
    168   // ---
    169 
    170   Handle<Code> ComputeLoadElementPolymorphic(MapHandleList* receiver_maps);
    171   Handle<Code> ComputeStoreElementPolymorphic(MapHandleList* receiver_maps,
    172                                               KeyedAccessStoreMode store_mode,
    173                                               StrictModeFlag strict_mode);
    174 
    175   Handle<Code> ComputePolymorphicIC(TypeHandleList* types,
    176                                     CodeHandleList* handlers,
    177                                     int number_of_valid_maps,
    178                                     Handle<Name> name,
    179                                     ExtraICState extra_ic_state);
    180 
    181   // Finds the Code object stored in the Heap::non_monomorphic_cache().
    182   Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
    183 
    184 #ifdef ENABLE_DEBUGGER_SUPPORT
    185   Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
    186 
    187   Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
    188 #endif
    189 
    190   // Update cache for entry hash(name, map).
    191   Code* Set(Name* name, Map* map, Code* code);
    192 
    193   // Clear the lookup table (@ mark compact collection).
    194   void Clear();
    195 
    196   // Collect all maps that match the name and flags.
    197   void CollectMatchingMaps(SmallMapList* types,
    198                            Handle<Name> name,
    199                            Code::Flags flags,
    200                            Handle<Context> native_context,
    201                            Zone* zone);
    202 
    203   // Generate code for probing the stub cache table.
    204   // Arguments extra, extra2 and extra3 may be used to pass additional scratch
    205   // registers. Set to no_reg if not needed.
    206   void GenerateProbe(MacroAssembler* masm,
    207                      Code::Flags flags,
    208                      Register receiver,
    209                      Register name,
    210                      Register scratch,
    211                      Register extra,
    212                      Register extra2 = no_reg,
    213                      Register extra3 = no_reg);
    214 
    215   enum Table {
    216     kPrimary,
    217     kSecondary
    218   };
    219 
    220 
    221   SCTableReference key_reference(StubCache::Table table) {
    222     return SCTableReference(
    223         reinterpret_cast<Address>(&first_entry(table)->key));
    224   }
    225 
    226 
    227   SCTableReference map_reference(StubCache::Table table) {
    228     return SCTableReference(
    229         reinterpret_cast<Address>(&first_entry(table)->map));
    230   }
    231 
    232 
    233   SCTableReference value_reference(StubCache::Table table) {
    234     return SCTableReference(
    235         reinterpret_cast<Address>(&first_entry(table)->value));
    236   }
    237 
    238 
    239   StubCache::Entry* first_entry(StubCache::Table table) {
    240     switch (table) {
    241       case StubCache::kPrimary: return StubCache::primary_;
    242       case StubCache::kSecondary: return StubCache::secondary_;
    243     }
    244     UNREACHABLE();
    245     return NULL;
    246   }
    247 
    248   Isolate* isolate() { return isolate_; }
    249   Heap* heap() { return isolate()->heap(); }
    250   Factory* factory() { return isolate()->factory(); }
    251 
    252   // These constants describe the structure of the interceptor arguments on the
    253   // stack. The arguments are pushed by the (platform-specific)
    254   // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
    255   // LoadWithInterceptor.
    256   static const int kInterceptorArgsNameIndex = 0;
    257   static const int kInterceptorArgsInfoIndex = 1;
    258   static const int kInterceptorArgsThisIndex = 2;
    259   static const int kInterceptorArgsHolderIndex = 3;
    260   static const int kInterceptorArgsLength = 4;
    261 
    262  private:
    263   explicit StubCache(Isolate* isolate);
    264 
    265   Handle<Code> ComputeCallInitialize(int argc,
    266                                      RelocInfo::Mode mode,
    267                                      Code::Kind kind);
    268 
    269   // The stub cache has a primary and secondary level.  The two levels have
    270   // different hashing algorithms in order to avoid simultaneous collisions
    271   // in both caches.  Unlike a probing strategy (quadratic or otherwise) the
    272   // update strategy on updates is fairly clear and simple:  Any existing entry
    273   // in the primary cache is moved to the secondary cache, and secondary cache
    274   // entries are overwritten.
    275 
    276   // Hash algorithm for the primary table.  This algorithm is replicated in
    277   // assembler for every architecture.  Returns an index into the table that
    278   // is scaled by 1 << kHeapObjectTagSize.
    279   static int PrimaryOffset(Name* name, Code::Flags flags, Map* map) {
    280     // This works well because the heap object tag size and the hash
    281     // shift are equal.  Shifting down the length field to get the
    282     // hash code would effectively throw away two bits of the hash
    283     // code.
    284     STATIC_ASSERT(kHeapObjectTagSize == Name::kHashShift);
    285     // Compute the hash of the name (use entire hash field).
    286     ASSERT(name->HasHashCode());
    287     uint32_t field = name->hash_field();
    288     // Using only the low bits in 64-bit mode is unlikely to increase the
    289     // risk of collision even if the heap is spread over an area larger than
    290     // 4Gb (and not at all if it isn't).
    291     uint32_t map_low32bits =
    292         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
    293     // We always set the in_loop bit to zero when generating the lookup code
    294     // so do it here too so the hash codes match.
    295     uint32_t iflags =
    296         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
    297     // Base the offset on a simple combination of name, flags, and map.
    298     uint32_t key = (map_low32bits + field) ^ iflags;
    299     return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
    300   }
    301 
    302   // Hash algorithm for the secondary table.  This algorithm is replicated in
    303   // assembler for every architecture.  Returns an index into the table that
    304   // is scaled by 1 << kHeapObjectTagSize.
    305   static int SecondaryOffset(Name* name, Code::Flags flags, int seed) {
    306     // Use the seed from the primary cache in the secondary cache.
    307     uint32_t name_low32bits =
    308         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
    309     // We always set the in_loop bit to zero when generating the lookup code
    310     // so do it here too so the hash codes match.
    311     uint32_t iflags =
    312         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
    313     uint32_t key = (seed - name_low32bits) + iflags;
    314     return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
    315   }
    316 
    317   // Compute the entry for a given offset in exactly the same way as
    318   // we do in generated code.  We generate an hash code that already
    319   // ends in Name::kHashShift 0s.  Then we multiply it so it is a multiple
    320   // of sizeof(Entry).  This makes it easier to avoid making mistakes
    321   // in the hashed offset computations.
    322   static Entry* entry(Entry* table, int offset) {
    323     const int multiplier = sizeof(*table) >> Name::kHashShift;
    324     return reinterpret_cast<Entry*>(
    325         reinterpret_cast<Address>(table) + offset * multiplier);
    326   }
    327 
    328   static const int kPrimaryTableBits = 11;
    329   static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
    330   static const int kSecondaryTableBits = 9;
    331   static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
    332 
    333   Entry primary_[kPrimaryTableSize];
    334   Entry secondary_[kSecondaryTableSize];
    335   Isolate* isolate_;
    336 
    337   friend class Isolate;
    338   friend class SCTableReference;
    339 
    340   DISALLOW_COPY_AND_ASSIGN(StubCache);
    341 };
    342 
    343 
    344 // ------------------------------------------------------------------------
    345 
    346 
    347 // Support functions for IC stubs for callbacks.
    348 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
    349 
    350 
    351 // Support functions for IC stubs for interceptors.
    352 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
    353 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
    354 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
    355 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
    356 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
    357 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
    358 
    359 
    360 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
    361 enum IcCheckType { ELEMENT, PROPERTY };
    362 
    363 
    364 // The stub compilers compile stubs for the stub cache.
    365 class StubCompiler BASE_EMBEDDED {
    366  public:
    367   explicit StubCompiler(Isolate* isolate,
    368                         ExtraICState extra_ic_state = kNoExtraICState)
    369       : isolate_(isolate), extra_ic_state_(extra_ic_state),
    370         masm_(isolate, NULL, 256), failure_(NULL) { }
    371 
    372   // Functions to compile either CallIC or KeyedCallIC.  The specific kind
    373   // is extracted from the code flags.
    374   Handle<Code> CompileCallInitialize(Code::Flags flags);
    375   Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
    376   Handle<Code> CompileCallNormal(Code::Flags flags);
    377   Handle<Code> CompileCallMegamorphic(Code::Flags flags);
    378   Handle<Code> CompileCallArguments(Code::Flags flags);
    379   Handle<Code> CompileCallMiss(Code::Flags flags);
    380 
    381 #ifdef ENABLE_DEBUGGER_SUPPORT
    382   Handle<Code> CompileCallDebugBreak(Code::Flags flags);
    383   Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
    384 #endif
    385 
    386   // Static functions for generating parts of stubs.
    387   static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
    388                                                   int index,
    389                                                   Register prototype);
    390 
    391   // Helper function used to check that the dictionary doesn't contain
    392   // the property. This function may return false negatives, so miss_label
    393   // must always call a backup property check that is complete.
    394   // This function is safe to call if the receiver has fast properties.
    395   // Name must be unique and receiver must be a heap object.
    396   static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
    397                                                Label* miss_label,
    398                                                Register receiver,
    399                                                Handle<Name> name,
    400                                                Register r0,
    401                                                Register r1);
    402 
    403   // Generates prototype loading code that uses the objects from the
    404   // context we were in when this function was called. If the context
    405   // has changed, a jump to miss is performed. This ties the generated
    406   // code to a particular context and so must not be used in cases
    407   // where the generated code is not allowed to have references to
    408   // objects from a context.
    409   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
    410                                                         int index,
    411                                                         Register prototype,
    412                                                         Label* miss);
    413 
    414   static void GenerateFastPropertyLoad(MacroAssembler* masm,
    415                                        Register dst,
    416                                        Register src,
    417                                        bool inobject,
    418                                        int index,
    419                                        Representation representation);
    420 
    421   static void GenerateLoadArrayLength(MacroAssembler* masm,
    422                                       Register receiver,
    423                                       Register scratch,
    424                                       Label* miss_label);
    425 
    426   static void GenerateLoadStringLength(MacroAssembler* masm,
    427                                        Register receiver,
    428                                        Register scratch1,
    429                                        Register scratch2,
    430                                        Label* miss_label);
    431 
    432   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
    433                                             Register receiver,
    434                                             Register scratch1,
    435                                             Register scratch2,
    436                                             Label* miss_label);
    437 
    438   // Generate code to check that a global property cell is empty. Create
    439   // the property cell at compilation time if no cell exists for the
    440   // property.
    441   static void GenerateCheckPropertyCell(MacroAssembler* masm,
    442                                         Handle<JSGlobalObject> global,
    443                                         Handle<Name> name,
    444                                         Register scratch,
    445                                         Label* miss);
    446 
    447   static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
    448 
    449   // Generates code that verifies that the property holder has not changed
    450   // (checking maps of objects in the prototype chain for fast and global
    451   // objects or doing negative lookup for slow objects, ensures that the
    452   // property cells for global objects are still empty) and checks that the map
    453   // of the holder has not changed. If necessary the function also generates
    454   // code for security check in case of global object holders. Helps to make
    455   // sure that the current IC is still valid.
    456   //
    457   // The scratch and holder registers are always clobbered, but the object
    458   // register is only clobbered if it the same as the holder register. The
    459   // function returns a register containing the holder - either object_reg or
    460   // holder_reg.
    461   // The function can optionally (when save_at_depth !=
    462   // kInvalidProtoDepth) save the object at the given depth by moving
    463   // it to [esp + kPointerSize].
    464   Register CheckPrototypes(Handle<Type> type,
    465                            Register object_reg,
    466                            Handle<JSObject> holder,
    467                            Register holder_reg,
    468                            Register scratch1,
    469                            Register scratch2,
    470                            Handle<Name> name,
    471                            Label* miss,
    472                            PrototypeCheckType check = CHECK_ALL_MAPS) {
    473     return CheckPrototypes(type, object_reg, holder, holder_reg, scratch1,
    474                            scratch2, name, kInvalidProtoDepth, miss, check);
    475   }
    476 
    477   Register CheckPrototypes(Handle<Type> type,
    478                            Register object_reg,
    479                            Handle<JSObject> holder,
    480                            Register holder_reg,
    481                            Register scratch1,
    482                            Register scratch2,
    483                            Handle<Name> name,
    484                            int save_at_depth,
    485                            Label* miss,
    486                            PrototypeCheckType check = CHECK_ALL_MAPS);
    487 
    488   void GenerateBooleanCheck(Register object, Label* miss);
    489 
    490  protected:
    491   Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
    492   Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
    493 
    494   ExtraICState extra_state() { return extra_ic_state_; }
    495 
    496   MacroAssembler* masm() { return &masm_; }
    497   void set_failure(Failure* failure) { failure_ = failure; }
    498 
    499   static void LookupPostInterceptor(Handle<JSObject> holder,
    500                                     Handle<Name> name,
    501                                     LookupResult* lookup);
    502 
    503   Isolate* isolate() { return isolate_; }
    504   Heap* heap() { return isolate()->heap(); }
    505   Factory* factory() { return isolate()->factory(); }
    506 
    507   static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
    508 
    509  private:
    510   Isolate* isolate_;
    511   const ExtraICState extra_ic_state_;
    512   MacroAssembler masm_;
    513   Failure* failure_;
    514 };
    515 
    516 
    517 enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
    518 
    519 
    520 class BaseLoadStoreStubCompiler: public StubCompiler {
    521  public:
    522   BaseLoadStoreStubCompiler(Isolate* isolate,
    523                             Code::Kind kind,
    524                             ExtraICState extra_ic_state = kNoExtraICState,
    525                             InlineCacheHolderFlag cache_holder = OWN_MAP)
    526       : StubCompiler(isolate, extra_ic_state),
    527         kind_(kind),
    528         cache_holder_(cache_holder) {
    529     InitializeRegisters();
    530   }
    531   virtual ~BaseLoadStoreStubCompiler() { }
    532 
    533   Handle<Code> CompileMonomorphicIC(Handle<Type> type,
    534                                     Handle<Code> handler,
    535                                     Handle<Name> name);
    536 
    537   Handle<Code> CompilePolymorphicIC(TypeHandleList* types,
    538                                     CodeHandleList* handlers,
    539                                     Handle<Name> name,
    540                                     Code::StubType type,
    541                                     IcCheckType check);
    542 
    543   virtual void GenerateNameCheck(Handle<Name> name,
    544                                  Register name_reg,
    545                                  Label* miss) { }
    546 
    547   static Builtins::Name MissBuiltin(Code::Kind kind) {
    548     switch (kind) {
    549       case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
    550       case Code::STORE_IC: return Builtins::kStoreIC_Miss;
    551       case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
    552       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
    553       default: UNREACHABLE();
    554     }
    555     return Builtins::kLoadIC_Miss;
    556   }
    557 
    558  protected:
    559   virtual Register HandlerFrontendHeader(Handle<Type> type,
    560                                          Register object_reg,
    561                                          Handle<JSObject> holder,
    562                                          Handle<Name> name,
    563                                          Label* miss) = 0;
    564 
    565   virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss) = 0;
    566 
    567   Register HandlerFrontend(Handle<Type> type,
    568                            Register object_reg,
    569                            Handle<JSObject> holder,
    570                            Handle<Name> name);
    571 
    572   Handle<Code> GetCode(Code::Kind kind,
    573                        Code::StubType type,
    574                        Handle<Name> name);
    575 
    576   Handle<Code> GetICCode(Code::Kind kind,
    577                          Code::StubType type,
    578                          Handle<Name> name,
    579                          InlineCacheState state = MONOMORPHIC);
    580   Code::Kind kind() { return kind_; }
    581 
    582   Logger::LogEventsAndTags log_kind(Handle<Code> code) {
    583     if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
    584     if (kind_ == Code::LOAD_IC) {
    585       return code->ic_state() == MONOMORPHIC
    586           ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
    587     } else if (kind_ == Code::KEYED_LOAD_IC) {
    588       return code->ic_state() == MONOMORPHIC
    589           ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
    590     } else if (kind_ == Code::STORE_IC) {
    591       return code->ic_state() == MONOMORPHIC
    592           ? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
    593     } else {
    594       return code->ic_state() == MONOMORPHIC
    595           ? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
    596     }
    597   }
    598   void JitEvent(Handle<Name> name, Handle<Code> code);
    599 
    600   virtual Register receiver() = 0;
    601   virtual Register name() = 0;
    602   virtual Register scratch1() = 0;
    603   virtual Register scratch2() = 0;
    604   virtual Register scratch3() = 0;
    605 
    606   void InitializeRegisters();
    607 
    608   bool IncludesNumberType(TypeHandleList* types);
    609 
    610   Code::Kind kind_;
    611   InlineCacheHolderFlag cache_holder_;
    612   Register* registers_;
    613 };
    614 
    615 
    616 class LoadStubCompiler: public BaseLoadStoreStubCompiler {
    617  public:
    618   LoadStubCompiler(Isolate* isolate,
    619                    ExtraICState extra_ic_state = kNoExtraICState,
    620                    InlineCacheHolderFlag cache_holder = OWN_MAP,
    621                    Code::Kind kind = Code::LOAD_IC)
    622       : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state,
    623                                   cache_holder) { }
    624   virtual ~LoadStubCompiler() { }
    625 
    626   Handle<Code> CompileLoadField(Handle<Type> type,
    627                                 Handle<JSObject> holder,
    628                                 Handle<Name> name,
    629                                 PropertyIndex index,
    630                                 Representation representation);
    631 
    632   Handle<Code> CompileLoadCallback(Handle<Type> type,
    633                                    Handle<JSObject> holder,
    634                                    Handle<Name> name,
    635                                    Handle<ExecutableAccessorInfo> callback);
    636 
    637   Handle<Code> CompileLoadCallback(Handle<Type> type,
    638                                    Handle<JSObject> holder,
    639                                    Handle<Name> name,
    640                                    const CallOptimization& call_optimization);
    641 
    642   Handle<Code> CompileLoadConstant(Handle<Type> type,
    643                                    Handle<JSObject> holder,
    644                                    Handle<Name> name,
    645                                    Handle<Object> value);
    646 
    647   Handle<Code> CompileLoadInterceptor(Handle<Type> type,
    648                                       Handle<JSObject> holder,
    649                                       Handle<Name> name);
    650 
    651   Handle<Code> CompileLoadViaGetter(Handle<Type> type,
    652                                     Handle<JSObject> holder,
    653                                     Handle<Name> name,
    654                                     Handle<JSFunction> getter);
    655 
    656   static void GenerateLoadViaGetter(MacroAssembler* masm,
    657                                     Register receiver,
    658                                     Handle<JSFunction> getter);
    659 
    660   Handle<Code> CompileLoadNonexistent(Handle<Type> type,
    661                                       Handle<JSObject> last,
    662                                       Handle<Name> name);
    663 
    664   Handle<Code> CompileLoadGlobal(Handle<Type> type,
    665                                  Handle<GlobalObject> holder,
    666                                  Handle<PropertyCell> cell,
    667                                  Handle<Name> name,
    668                                  bool is_dont_delete);
    669 
    670   static Register* registers();
    671 
    672  protected:
    673   virtual Register HandlerFrontendHeader(Handle<Type> type,
    674                                          Register object_reg,
    675                                          Handle<JSObject> holder,
    676                                          Handle<Name> name,
    677                                          Label* miss);
    678 
    679   virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
    680 
    681   Register CallbackHandlerFrontend(Handle<Type> type,
    682                                    Register object_reg,
    683                                    Handle<JSObject> holder,
    684                                    Handle<Name> name,
    685                                    Handle<Object> callback);
    686   void NonexistentHandlerFrontend(Handle<Type> type,
    687                                   Handle<JSObject> last,
    688                                   Handle<Name> name);
    689 
    690   void GenerateLoadField(Register reg,
    691                          Handle<JSObject> holder,
    692                          PropertyIndex field,
    693                          Representation representation);
    694   void GenerateLoadConstant(Handle<Object> value);
    695   void GenerateLoadCallback(Register reg,
    696                             Handle<ExecutableAccessorInfo> callback);
    697   void GenerateLoadCallback(const CallOptimization& call_optimization);
    698   void GenerateLoadInterceptor(Register holder_reg,
    699                                Handle<Object> object,
    700                                Handle<JSObject> holder,
    701                                LookupResult* lookup,
    702                                Handle<Name> name);
    703   void GenerateLoadPostInterceptor(Register reg,
    704                                    Handle<JSObject> interceptor_holder,
    705                                    Handle<Name> name,
    706                                    LookupResult* lookup);
    707 
    708   virtual Register receiver() { return registers_[0]; }
    709   virtual Register name()     { return registers_[1]; }
    710   virtual Register scratch1() { return registers_[2]; }
    711   virtual Register scratch2() { return registers_[3]; }
    712   virtual Register scratch3() { return registers_[4]; }
    713   Register scratch4() { return registers_[5]; }
    714 };
    715 
    716 
    717 class KeyedLoadStubCompiler: public LoadStubCompiler {
    718  public:
    719   KeyedLoadStubCompiler(Isolate* isolate,
    720                         ExtraICState extra_ic_state = kNoExtraICState,
    721                         InlineCacheHolderFlag cache_holder = OWN_MAP)
    722       : LoadStubCompiler(isolate, extra_ic_state, cache_holder,
    723                          Code::KEYED_LOAD_IC) { }
    724 
    725   Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
    726 
    727   void CompileElementHandlers(MapHandleList* receiver_maps,
    728                               CodeHandleList* handlers);
    729 
    730   static void GenerateLoadDictionaryElement(MacroAssembler* masm);
    731 
    732  protected:
    733   static Register* registers();
    734 
    735  private:
    736   virtual void GenerateNameCheck(Handle<Name> name,
    737                                  Register name_reg,
    738                                  Label* miss);
    739   friend class BaseLoadStoreStubCompiler;
    740 };
    741 
    742 
    743 class StoreStubCompiler: public BaseLoadStoreStubCompiler {
    744  public:
    745   StoreStubCompiler(Isolate* isolate,
    746                     ExtraICState extra_ic_state,
    747                     Code::Kind kind = Code::STORE_IC)
    748       : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state) {}
    749 
    750   virtual ~StoreStubCompiler() { }
    751 
    752   Handle<Code> CompileStoreTransition(Handle<JSObject> object,
    753                                       LookupResult* lookup,
    754                                       Handle<Map> transition,
    755                                       Handle<Name> name);
    756 
    757   Handle<Code> CompileStoreField(Handle<JSObject> object,
    758                                  LookupResult* lookup,
    759                                  Handle<Name> name);
    760 
    761   void GenerateNegativeHolderLookup(MacroAssembler* masm,
    762                                     Handle<JSObject> holder,
    763                                     Register holder_reg,
    764                                     Handle<Name> name,
    765                                     Label* miss);
    766 
    767   void GenerateStoreTransition(MacroAssembler* masm,
    768                                Handle<JSObject> object,
    769                                LookupResult* lookup,
    770                                Handle<Map> transition,
    771                                Handle<Name> name,
    772                                Register receiver_reg,
    773                                Register name_reg,
    774                                Register value_reg,
    775                                Register scratch1,
    776                                Register scratch2,
    777                                Register scratch3,
    778                                Label* miss_label,
    779                                Label* slow);
    780 
    781   void GenerateStoreField(MacroAssembler* masm,
    782                           Handle<JSObject> object,
    783                           LookupResult* lookup,
    784                           Register receiver_reg,
    785                           Register name_reg,
    786                           Register value_reg,
    787                           Register scratch1,
    788                           Register scratch2,
    789                           Label* miss_label);
    790 
    791   Handle<Code> CompileStoreCallback(Handle<JSObject> object,
    792                                     Handle<JSObject> holder,
    793                                     Handle<Name> name,
    794                                     Handle<ExecutableAccessorInfo> callback);
    795 
    796   Handle<Code> CompileStoreCallback(Handle<JSObject> object,
    797                                     Handle<JSObject> holder,
    798                                     Handle<Name> name,
    799                                     const CallOptimization& call_optimization);
    800 
    801   static void GenerateStoreViaSetter(MacroAssembler* masm,
    802                                      Handle<JSFunction> setter);
    803 
    804   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object,
    805                                      Handle<JSObject> holder,
    806                                      Handle<Name> name,
    807                                      Handle<JSFunction> setter);
    808 
    809   Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
    810                                        Handle<Name> name);
    811 
    812   static Builtins::Name SlowBuiltin(Code::Kind kind) {
    813     switch (kind) {
    814       case Code::STORE_IC: return Builtins::kStoreIC_Slow;
    815       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow;
    816       default: UNREACHABLE();
    817     }
    818     return Builtins::kStoreIC_Slow;
    819   }
    820 
    821  protected:
    822   virtual Register HandlerFrontendHeader(Handle<Type> type,
    823                                          Register object_reg,
    824                                          Handle<JSObject> holder,
    825                                          Handle<Name> name,
    826                                          Label* miss);
    827 
    828   virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
    829   void GenerateRestoreName(MacroAssembler* masm,
    830                            Label* label,
    831                            Handle<Name> name);
    832 
    833   virtual Register receiver() { return registers_[0]; }
    834   virtual Register name()     { return registers_[1]; }
    835   Register value()    { return registers_[2]; }
    836   virtual Register scratch1() { return registers_[3]; }
    837   virtual Register scratch2() { return registers_[4]; }
    838   virtual Register scratch3() { return registers_[5]; }
    839 
    840  protected:
    841   static Register* registers();
    842 
    843  private:
    844   friend class BaseLoadStoreStubCompiler;
    845 };
    846 
    847 
    848 class KeyedStoreStubCompiler: public StoreStubCompiler {
    849  public:
    850   KeyedStoreStubCompiler(Isolate* isolate,
    851                          ExtraICState extra_ic_state)
    852       : StoreStubCompiler(isolate, extra_ic_state, Code::KEYED_STORE_IC) {}
    853 
    854   Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
    855 
    856   Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
    857                                        CodeHandleList* handler_stubs,
    858                                        MapHandleList* transitioned_maps);
    859 
    860   Handle<Code> CompileStoreElementPolymorphic(MapHandleList* receiver_maps);
    861 
    862   static void GenerateStoreDictionaryElement(MacroAssembler* masm);
    863 
    864  protected:
    865   static Register* registers();
    866 
    867   KeyedAccessStoreMode store_mode() {
    868     return KeyedStoreIC::GetKeyedAccessStoreMode(extra_state());
    869   }
    870 
    871  private:
    872   Register transition_map() {
    873     return registers()[3];
    874   }
    875 
    876   virtual void GenerateNameCheck(Handle<Name> name,
    877                                  Register name_reg,
    878                                  Label* miss);
    879   friend class BaseLoadStoreStubCompiler;
    880 };
    881 
    882 
    883 // Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
    884 // IC stubs.
    885 #define CUSTOM_CALL_IC_GENERATORS(V)            \
    886   V(ArrayPush)                                  \
    887   V(ArrayPop)                                   \
    888   V(StringCharCodeAt)                           \
    889   V(StringCharAt)                               \
    890   V(StringFromCharCode)                         \
    891   V(MathFloor)                                  \
    892   V(MathAbs)                                    \
    893   V(ArrayCode)
    894 
    895 
    896 #define SITE_SPECIFIC_CALL_GENERATORS(V)        \
    897   V(ArrayCode)
    898 
    899 
    900 class CallStubCompiler: public StubCompiler {
    901  public:
    902   CallStubCompiler(Isolate* isolate,
    903                    int argc,
    904                    Code::Kind kind,
    905                    ExtraICState extra_state,
    906                    InlineCacheHolderFlag cache_holder = OWN_MAP);
    907 
    908   Handle<Code> CompileCallField(Handle<JSObject> object,
    909                                 Handle<JSObject> holder,
    910                                 PropertyIndex index,
    911                                 Handle<Name> name);
    912 
    913   // Patch the global proxy over the global object if the global object is the
    914   // receiver.
    915   void PatchGlobalProxy(Handle<Object> object);
    916 
    917   // Returns the register containing the holder of |name|.
    918   Register HandlerFrontendHeader(Handle<Object> object,
    919                                  Handle<JSObject> holder,
    920                                  Handle<Name> name,
    921                                  CheckType check,
    922                                  Label* miss);
    923   void HandlerFrontendFooter(Label* miss);
    924 
    925   void GenerateJumpFunctionIgnoreReceiver(Handle<JSFunction> function);
    926   void GenerateJumpFunction(Handle<Object> object,
    927                             Handle<JSFunction> function);
    928   void GenerateJumpFunction(Handle<Object> object,
    929                             Register function,
    930                             Label* miss);
    931   // Use to call |actual_closure|, a closure with the same shared function info
    932   // as |function|.
    933   void GenerateJumpFunction(Handle<Object> object,
    934                             Register actual_closure,
    935                             Handle<JSFunction> function);
    936 
    937   Handle<Code> CompileCallConstant(Handle<Object> object,
    938                                    Handle<JSObject> holder,
    939                                    Handle<Name> name,
    940                                    CheckType check,
    941                                    Handle<JSFunction> function);
    942 
    943   Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
    944                                       Handle<JSObject> holder,
    945                                       Handle<Name> name);
    946 
    947   Handle<Code> CompileCallGlobal(Handle<JSObject> object,
    948                                  Handle<GlobalObject> holder,
    949                                  Handle<PropertyCell> cell,
    950                                  Handle<JSFunction> function,
    951                                  Handle<Name> name);
    952 
    953   static bool HasCustomCallGenerator(Handle<JSFunction> function);
    954   static bool CanBeCached(Handle<JSFunction> function);
    955 
    956  private:
    957   // Compiles a custom call constant/global IC.  For constant calls cell is
    958   // NULL.  Returns an empty handle if there is no custom call code for the
    959   // given function.
    960   Handle<Code> CompileCustomCall(Handle<Object> object,
    961                                  Handle<JSObject> holder,
    962                                  Handle<Cell> cell,
    963                                  Handle<JSFunction> function,
    964                                  Handle<String> name,
    965                                  Code::StubType type);
    966 
    967 #define DECLARE_CALL_GENERATOR(name)                                    \
    968   Handle<Code> Compile##name##Call(Handle<Object> object,               \
    969                                    Handle<JSObject> holder,             \
    970                                    Handle<Cell> cell,                   \
    971                                    Handle<JSFunction> function,         \
    972                                    Handle<String> fname,                \
    973                                    Code::StubType type);
    974   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
    975 #undef DECLARE_CALL_GENERATOR
    976 
    977   Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
    978                                   Handle<Object> object,
    979                                   Handle<JSObject> holder,
    980                                   Handle<Cell> cell,
    981                                   Handle<JSFunction> function,
    982                                   Handle<String> name);
    983 
    984   CallKind call_kind();
    985 
    986   Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
    987   Handle<Code> GetCode(Handle<JSFunction> function);
    988 
    989   const ParameterCount& arguments() { return arguments_; }
    990 
    991   void GenerateNameCheck(Handle<Name> name, Label* miss);
    992 
    993   // Generates code to load the function from the cell checking that
    994   // it still contains the same function.
    995   void GenerateLoadFunctionFromCell(Handle<Cell> cell,
    996                                     Handle<JSFunction> function,
    997                                     Label* miss);
    998 
    999   void GenerateFunctionCheck(Register function, Register scratch, Label* miss);
   1000 
   1001   // Generates a jump to CallIC miss stub.
   1002   void GenerateMissBranch();
   1003 
   1004   const ParameterCount arguments_;
   1005   const Code::Kind kind_;
   1006   const InlineCacheHolderFlag cache_holder_;
   1007 };
   1008 
   1009 
   1010 // Holds information about possible function call optimizations.
   1011 class CallOptimization BASE_EMBEDDED {
   1012  public:
   1013   explicit CallOptimization(LookupResult* lookup);
   1014 
   1015   explicit CallOptimization(Handle<JSFunction> function);
   1016 
   1017   bool is_constant_call() const {
   1018     return !constant_function_.is_null();
   1019   }
   1020 
   1021   Handle<JSFunction> constant_function() const {
   1022     ASSERT(is_constant_call());
   1023     return constant_function_;
   1024   }
   1025 
   1026   bool is_simple_api_call() const {
   1027     return is_simple_api_call_;
   1028   }
   1029 
   1030   Handle<FunctionTemplateInfo> expected_receiver_type() const {
   1031     ASSERT(is_simple_api_call());
   1032     return expected_receiver_type_;
   1033   }
   1034 
   1035   Handle<CallHandlerInfo> api_call_info() const {
   1036     ASSERT(is_simple_api_call());
   1037     return api_call_info_;
   1038   }
   1039 
   1040   // Returns the depth of the object having the expected type in the
   1041   // prototype chain between the two arguments.
   1042   int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
   1043                                       Handle<JSObject> holder) const;
   1044 
   1045   bool IsCompatibleReceiver(Object* receiver) {
   1046     ASSERT(is_simple_api_call());
   1047     if (expected_receiver_type_.is_null()) return true;
   1048     return expected_receiver_type_->IsTemplateFor(receiver);
   1049   }
   1050 
   1051  private:
   1052   void Initialize(Handle<JSFunction> function);
   1053 
   1054   // Determines whether the given function can be called using the
   1055   // fast api call builtin.
   1056   void AnalyzePossibleApiFunction(Handle<JSFunction> function);
   1057 
   1058   Handle<JSFunction> constant_function_;
   1059   bool is_simple_api_call_;
   1060   Handle<FunctionTemplateInfo> expected_receiver_type_;
   1061   Handle<CallHandlerInfo> api_call_info_;
   1062 };
   1063 
   1064 
   1065 } }  // namespace v8::internal
   1066 
   1067 #endif  // V8_STUB_CACHE_H_
   1068