Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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 "arguments.h"
     32 #include "macro-assembler.h"
     33 #include "zone-inl.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 
     39 // The stub cache is used for megamorphic calls and property accesses.
     40 // It maps (map, name, type)->Code*
     41 
     42 // The design of the table uses the inline cache stubs used for
     43 // mono-morphic calls. The beauty of this, we do not have to
     44 // invalidate the cache whenever a prototype map is changed.  The stub
     45 // validates the map chain as in the mono-morphic case.
     46 
     47 class StubCache;
     48 
     49 class SCTableReference {
     50  public:
     51   Address address() const { return address_; }
     52 
     53  private:
     54   explicit SCTableReference(Address address) : address_(address) {}
     55 
     56   Address address_;
     57 
     58   friend class StubCache;
     59 };
     60 
     61 
     62 class StubCache {
     63  public:
     64   struct Entry {
     65     String* key;
     66     Code* value;
     67   };
     68 
     69   void Initialize(bool create_heap_objects);
     70 
     71 
     72   // Computes the right stub matching. Inserts the result in the
     73   // cache before returning.  This might compile a stub if needed.
     74   MUST_USE_RESULT MaybeObject* ComputeLoadNonexistent(
     75       String* name,
     76       JSObject* receiver);
     77 
     78   MUST_USE_RESULT MaybeObject* ComputeLoadField(String* name,
     79                                                 JSObject* receiver,
     80                                                 JSObject* holder,
     81                                                 int field_index);
     82 
     83   MUST_USE_RESULT MaybeObject* ComputeLoadCallback(
     84       String* name,
     85       JSObject* receiver,
     86       JSObject* holder,
     87       AccessorInfo* callback);
     88 
     89   MUST_USE_RESULT MaybeObject* ComputeLoadConstant(String* name,
     90                                                    JSObject* receiver,
     91                                                    JSObject* holder,
     92                                                    Object* value);
     93 
     94   MUST_USE_RESULT MaybeObject* ComputeLoadInterceptor(
     95       String* name,
     96       JSObject* receiver,
     97       JSObject* holder);
     98 
     99   MUST_USE_RESULT MaybeObject* ComputeLoadNormal();
    100 
    101 
    102   MUST_USE_RESULT MaybeObject* ComputeLoadGlobal(
    103       String* name,
    104       JSObject* receiver,
    105       GlobalObject* holder,
    106       JSGlobalPropertyCell* cell,
    107       bool is_dont_delete);
    108 
    109 
    110   // ---
    111 
    112   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadField(String* name,
    113                                                      JSObject* receiver,
    114                                                      JSObject* holder,
    115                                                      int field_index);
    116 
    117   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadCallback(
    118       String* name,
    119       JSObject* receiver,
    120       JSObject* holder,
    121       AccessorInfo* callback);
    122 
    123   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadConstant(
    124       String* name,
    125       JSObject* receiver,
    126       JSObject* holder,
    127       Object* value);
    128 
    129   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadInterceptor(
    130       String* name,
    131       JSObject* receiver,
    132       JSObject* holder);
    133 
    134   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadArrayLength(
    135       String* name,
    136       JSArray* receiver);
    137 
    138   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadStringLength(
    139       String* name,
    140       String* receiver);
    141 
    142   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadFunctionPrototype(
    143       String* name,
    144       JSFunction* receiver);
    145 
    146   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadSpecialized(
    147       JSObject* receiver);
    148 
    149   // ---
    150 
    151   MUST_USE_RESULT MaybeObject* ComputeStoreField(
    152       String* name,
    153       JSObject* receiver,
    154       int field_index,
    155       Map* transition,
    156       StrictModeFlag strict_mode);
    157 
    158   MUST_USE_RESULT MaybeObject* ComputeStoreNormal(
    159       StrictModeFlag strict_mode);
    160 
    161   MUST_USE_RESULT MaybeObject* ComputeStoreGlobal(
    162       String* name,
    163       GlobalObject* receiver,
    164       JSGlobalPropertyCell* cell,
    165       StrictModeFlag strict_mode);
    166 
    167   MUST_USE_RESULT MaybeObject* ComputeStoreCallback(
    168       String* name,
    169       JSObject* receiver,
    170       AccessorInfo* callback,
    171       StrictModeFlag strict_mode);
    172 
    173   MUST_USE_RESULT MaybeObject* ComputeStoreInterceptor(
    174       String* name,
    175       JSObject* receiver,
    176       StrictModeFlag strict_mode);
    177 
    178   // ---
    179 
    180   MUST_USE_RESULT MaybeObject* ComputeKeyedStoreField(
    181       String* name,
    182       JSObject* receiver,
    183       int field_index,
    184       Map* transition,
    185       StrictModeFlag strict_mode);
    186 
    187   MUST_USE_RESULT MaybeObject* ComputeKeyedStoreSpecialized(
    188       JSObject* receiver,
    189       StrictModeFlag strict_mode);
    190 
    191 
    192   MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
    193       JSObject* receiver,
    194       bool is_store,
    195       StrictModeFlag strict_mode);
    196 
    197   // ---
    198 
    199   MUST_USE_RESULT MaybeObject* ComputeCallField(int argc,
    200                                                 InLoopFlag in_loop,
    201                                                 Code::Kind,
    202                                                 String* name,
    203                                                 Object* object,
    204                                                 JSObject* holder,
    205                                                 int index);
    206 
    207   MUST_USE_RESULT MaybeObject* ComputeCallConstant(
    208       int argc,
    209       InLoopFlag in_loop,
    210       Code::Kind,
    211       Code::ExtraICState extra_ic_state,
    212       String* name,
    213       Object* object,
    214       JSObject* holder,
    215       JSFunction* function);
    216 
    217   MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
    218                                                  InLoopFlag in_loop,
    219                                                  Code::Kind,
    220                                                  String* name,
    221                                                  JSObject* receiver);
    222 
    223   MUST_USE_RESULT MaybeObject* ComputeCallInterceptor(int argc,
    224                                                       Code::Kind,
    225                                                       String* name,
    226                                                       Object* object,
    227                                                       JSObject* holder);
    228 
    229   MUST_USE_RESULT MaybeObject* ComputeCallGlobal(
    230       int argc,
    231       InLoopFlag in_loop,
    232       Code::Kind,
    233       String* name,
    234       JSObject* receiver,
    235       GlobalObject* holder,
    236       JSGlobalPropertyCell* cell,
    237       JSFunction* function);
    238 
    239   // ---
    240 
    241   MUST_USE_RESULT MaybeObject* ComputeCallInitialize(int argc,
    242                                                      InLoopFlag in_loop,
    243                                                      Code::Kind kind);
    244 
    245   Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
    246 
    247   Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
    248 
    249   MUST_USE_RESULT MaybeObject* ComputeCallPreMonomorphic(
    250       int argc,
    251       InLoopFlag in_loop,
    252       Code::Kind kind);
    253 
    254   MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
    255                                                  InLoopFlag in_loop,
    256                                                  Code::Kind kind);
    257 
    258   MUST_USE_RESULT MaybeObject* ComputeCallMegamorphic(int argc,
    259                                                       InLoopFlag in_loop,
    260                                                       Code::Kind kind);
    261 
    262   MUST_USE_RESULT MaybeObject* ComputeCallMiss(int argc, Code::Kind kind);
    263 
    264   // Finds the Code object stored in the Heap::non_monomorphic_cache().
    265   MUST_USE_RESULT Code* FindCallInitialize(int argc,
    266                                            InLoopFlag in_loop,
    267                                            Code::Kind kind);
    268 
    269 #ifdef ENABLE_DEBUGGER_SUPPORT
    270   MUST_USE_RESULT MaybeObject* ComputeCallDebugBreak(int argc, Code::Kind kind);
    271 
    272   MUST_USE_RESULT MaybeObject* ComputeCallDebugPrepareStepIn(int argc,
    273                                                              Code::Kind kind);
    274 #endif
    275 
    276   // Update cache for entry hash(name, map).
    277   Code* Set(String* name, Map* map, Code* code);
    278 
    279   // Clear the lookup table (@ mark compact collection).
    280   void Clear();
    281 
    282   // Collect all maps that match the name and flags.
    283   void CollectMatchingMaps(ZoneMapList* types,
    284                            String* name,
    285                            Code::Flags flags);
    286 
    287   // Generate code for probing the stub cache table.
    288   // Arguments extra and extra2 may be used to pass additional scratch
    289   // registers. Set to no_reg if not needed.
    290   void GenerateProbe(MacroAssembler* masm,
    291                      Code::Flags flags,
    292                      Register receiver,
    293                      Register name,
    294                      Register scratch,
    295                      Register extra,
    296                      Register extra2 = no_reg);
    297 
    298   enum Table {
    299     kPrimary,
    300     kSecondary
    301   };
    302 
    303 
    304   SCTableReference key_reference(StubCache::Table table) {
    305     return SCTableReference(
    306         reinterpret_cast<Address>(&first_entry(table)->key));
    307   }
    308 
    309 
    310   SCTableReference value_reference(StubCache::Table table) {
    311     return SCTableReference(
    312         reinterpret_cast<Address>(&first_entry(table)->value));
    313   }
    314 
    315 
    316   StubCache::Entry* first_entry(StubCache::Table table) {
    317     switch (table) {
    318       case StubCache::kPrimary: return StubCache::primary_;
    319       case StubCache::kSecondary: return StubCache::secondary_;
    320     }
    321     UNREACHABLE();
    322     return NULL;
    323   }
    324 
    325   Isolate* isolate() { return isolate_; }
    326   Heap* heap() { return isolate()->heap(); }
    327 
    328  private:
    329   explicit StubCache(Isolate* isolate);
    330 
    331   friend class Isolate;
    332   friend class SCTableReference;
    333   static const int kPrimaryTableSize = 2048;
    334   static const int kSecondaryTableSize = 512;
    335   Entry primary_[kPrimaryTableSize];
    336   Entry secondary_[kSecondaryTableSize];
    337 
    338   // Computes the hashed offsets for primary and secondary caches.
    339   RLYSTC int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
    340     // This works well because the heap object tag size and the hash
    341     // shift are equal.  Shifting down the length field to get the
    342     // hash code would effectively throw away two bits of the hash
    343     // code.
    344     ASSERT(kHeapObjectTagSize == String::kHashShift);
    345     // Compute the hash of the name (use entire hash field).
    346     ASSERT(name->HasHashCode());
    347     uint32_t field = name->hash_field();
    348     // Using only the low bits in 64-bit mode is unlikely to increase the
    349     // risk of collision even if the heap is spread over an area larger than
    350     // 4Gb (and not at all if it isn't).
    351     uint32_t map_low32bits =
    352         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
    353     // We always set the in_loop bit to zero when generating the lookup code
    354     // so do it here too so the hash codes match.
    355     uint32_t iflags =
    356         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
    357     // Base the offset on a simple combination of name, flags, and map.
    358     uint32_t key = (map_low32bits + field) ^ iflags;
    359     return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
    360   }
    361 
    362   RLYSTC int SecondaryOffset(String* name, Code::Flags flags, int seed) {
    363     // Use the seed from the primary cache in the secondary cache.
    364     uint32_t string_low32bits =
    365         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
    366     // We always set the in_loop bit to zero when generating the lookup code
    367     // so do it here too so the hash codes match.
    368     uint32_t iflags =
    369         (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
    370     uint32_t key = seed - string_low32bits + iflags;
    371     return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
    372   }
    373 
    374   // Compute the entry for a given offset in exactly the same way as
    375   // we do in generated code.  We generate an hash code that already
    376   // ends in String::kHashShift 0s.  Then we shift it so it is a multiple
    377   // of sizeof(Entry).  This makes it easier to avoid making mistakes
    378   // in the hashed offset computations.
    379   RLYSTC Entry* entry(Entry* table, int offset) {
    380     const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
    381     return reinterpret_cast<Entry*>(
    382         reinterpret_cast<Address>(table) + (offset << shift_amount));
    383   }
    384 
    385   Isolate* isolate_;
    386 
    387   DISALLOW_COPY_AND_ASSIGN(StubCache);
    388 };
    389 
    390 
    391 // ------------------------------------------------------------------------
    392 
    393 
    394 // Support functions for IC stubs for callbacks.
    395 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
    396 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
    397 
    398 
    399 // Support functions for IC stubs for interceptors.
    400 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
    401 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
    402 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
    403 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
    404 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
    405 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
    406 
    407 
    408 // The stub compiler compiles stubs for the stub cache.
    409 class StubCompiler BASE_EMBEDDED {
    410  public:
    411   StubCompiler()
    412       : scope_(), masm_(Isolate::Current(), NULL, 256), failure_(NULL) { }
    413 
    414   MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
    415   MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
    416   MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
    417   MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
    418   MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
    419 #ifdef ENABLE_DEBUGGER_SUPPORT
    420   MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
    421   MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
    422 #endif
    423 
    424   // Static functions for generating parts of stubs.
    425   static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
    426                                                   int index,
    427                                                   Register prototype);
    428 
    429   // Generates prototype loading code that uses the objects from the
    430   // context we were in when this function was called. If the context
    431   // has changed, a jump to miss is performed. This ties the generated
    432   // code to a particular context and so must not be used in cases
    433   // where the generated code is not allowed to have references to
    434   // objects from a context.
    435   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
    436                                                         int index,
    437                                                         Register prototype,
    438                                                         Label* miss);
    439 
    440   static void GenerateFastPropertyLoad(MacroAssembler* masm,
    441                                        Register dst, Register src,
    442                                        JSObject* holder, int index);
    443 
    444   static void GenerateLoadArrayLength(MacroAssembler* masm,
    445                                       Register receiver,
    446                                       Register scratch,
    447                                       Label* miss_label);
    448 
    449   static void GenerateLoadStringLength(MacroAssembler* masm,
    450                                        Register receiver,
    451                                        Register scratch1,
    452                                        Register scratch2,
    453                                        Label* miss_label,
    454                                        bool support_wrappers);
    455 
    456   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
    457                                             Register receiver,
    458                                             Register scratch1,
    459                                             Register scratch2,
    460                                             Label* miss_label);
    461 
    462   static void GenerateStoreField(MacroAssembler* masm,
    463                                  JSObject* object,
    464                                  int index,
    465                                  Map* transition,
    466                                  Register receiver_reg,
    467                                  Register name_reg,
    468                                  Register scratch,
    469                                  Label* miss_label);
    470 
    471   static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
    472 
    473   // Generates code that verifies that the property holder has not changed
    474   // (checking maps of objects in the prototype chain for fast and global
    475   // objects or doing negative lookup for slow objects, ensures that the
    476   // property cells for global objects are still empty) and checks that the map
    477   // of the holder has not changed. If necessary the function also generates
    478   // code for security check in case of global object holders. Helps to make
    479   // sure that the current IC is still valid.
    480   //
    481   // The scratch and holder registers are always clobbered, but the object
    482   // register is only clobbered if it the same as the holder register. The
    483   // function returns a register containing the holder - either object_reg or
    484   // holder_reg.
    485   // The function can optionally (when save_at_depth !=
    486   // kInvalidProtoDepth) save the object at the given depth by moving
    487   // it to [esp + kPointerSize].
    488 
    489   Register CheckPrototypes(JSObject* object,
    490                            Register object_reg,
    491                            JSObject* holder,
    492                            Register holder_reg,
    493                            Register scratch1,
    494                            Register scratch2,
    495                            String* name,
    496                            Label* miss) {
    497     return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
    498                            scratch2, name, kInvalidProtoDepth, miss);
    499   }
    500 
    501   Register CheckPrototypes(JSObject* object,
    502                            Register object_reg,
    503                            JSObject* holder,
    504                            Register holder_reg,
    505                            Register scratch1,
    506                            Register scratch2,
    507                            String* name,
    508                            int save_at_depth,
    509                            Label* miss);
    510 
    511  protected:
    512   MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
    513   MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
    514 
    515   MacroAssembler* masm() { return &masm_; }
    516   void set_failure(Failure* failure) { failure_ = failure; }
    517 
    518   void GenerateLoadField(JSObject* object,
    519                          JSObject* holder,
    520                          Register receiver,
    521                          Register scratch1,
    522                          Register scratch2,
    523                          Register scratch3,
    524                          int index,
    525                          String* name,
    526                          Label* miss);
    527 
    528   MaybeObject* GenerateLoadCallback(JSObject* object,
    529                                     JSObject* holder,
    530                                     Register receiver,
    531                                     Register name_reg,
    532                                     Register scratch1,
    533                                     Register scratch2,
    534                                     Register scratch3,
    535                                     AccessorInfo* callback,
    536                                     String* name,
    537                                     Label* miss);
    538 
    539   void GenerateLoadConstant(JSObject* object,
    540                             JSObject* holder,
    541                             Register receiver,
    542                             Register scratch1,
    543                             Register scratch2,
    544                             Register scratch3,
    545                             Object* value,
    546                             String* name,
    547                             Label* miss);
    548 
    549   void GenerateLoadInterceptor(JSObject* object,
    550                                JSObject* holder,
    551                                LookupResult* lookup,
    552                                Register receiver,
    553                                Register name_reg,
    554                                Register scratch1,
    555                                Register scratch2,
    556                                Register scratch3,
    557                                String* name,
    558                                Label* miss);
    559 
    560   static void LookupPostInterceptor(JSObject* holder,
    561                                     String* name,
    562                                     LookupResult* lookup);
    563 
    564   Isolate* isolate() { return scope_.isolate(); }
    565   Heap* heap() { return isolate()->heap(); }
    566   Factory* factory() { return isolate()->factory(); }
    567 
    568  private:
    569   HandleScope scope_;
    570   MacroAssembler masm_;
    571   Failure* failure_;
    572 };
    573 
    574 
    575 class LoadStubCompiler: public StubCompiler {
    576  public:
    577   MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
    578                                                       JSObject* object,
    579                                                       JSObject* last);
    580 
    581   MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
    582                                                 JSObject* holder,
    583                                                 int index,
    584                                                 String* name);
    585 
    586   MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
    587                                                    JSObject* object,
    588                                                    JSObject* holder,
    589                                                    AccessorInfo* callback);
    590 
    591   MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
    592                                                    JSObject* holder,
    593                                                    Object* value,
    594                                                    String* name);
    595 
    596   MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
    597                                                       JSObject* holder,
    598                                                       String* name);
    599 
    600   MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
    601                                                  GlobalObject* holder,
    602                                                  JSGlobalPropertyCell* cell,
    603                                                  String* name,
    604                                                  bool is_dont_delete);
    605 
    606  private:
    607   MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
    608 };
    609 
    610 
    611 class KeyedLoadStubCompiler: public StubCompiler {
    612  public:
    613   MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
    614                                                 JSObject* object,
    615                                                 JSObject* holder,
    616                                                 int index);
    617 
    618   MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
    619                                                    JSObject* object,
    620                                                    JSObject* holder,
    621                                                    AccessorInfo* callback);
    622 
    623   MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
    624                                                    JSObject* object,
    625                                                    JSObject* holder,
    626                                                    Object* value);
    627 
    628   MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
    629                                                       JSObject* holder,
    630                                                       String* name);
    631 
    632   MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
    633   MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
    634   MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
    635 
    636   MUST_USE_RESULT MaybeObject* CompileLoadSpecialized(JSObject* receiver);
    637 
    638  private:
    639   MaybeObject* GetCode(PropertyType type, String* name);
    640 };
    641 
    642 
    643 class StoreStubCompiler: public StubCompiler {
    644  public:
    645   explicit StoreStubCompiler(StrictModeFlag strict_mode)
    646     : strict_mode_(strict_mode) { }
    647 
    648   MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
    649                                                  int index,
    650                                                  Map* transition,
    651                                                  String* name);
    652 
    653   MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
    654                                                     AccessorInfo* callbacks,
    655                                                     String* name);
    656   MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
    657                                                        String* name);
    658   MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
    659                                                   JSGlobalPropertyCell* holder,
    660                                                   String* name);
    661 
    662 
    663  private:
    664   MaybeObject* GetCode(PropertyType type, String* name);
    665 
    666   StrictModeFlag strict_mode_;
    667 };
    668 
    669 
    670 class KeyedStoreStubCompiler: public StubCompiler {
    671  public:
    672   explicit KeyedStoreStubCompiler(StrictModeFlag strict_mode)
    673     : strict_mode_(strict_mode) { }
    674 
    675   MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
    676                                                  int index,
    677                                                  Map* transition,
    678                                                  String* name);
    679 
    680   MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
    681 
    682  private:
    683   MaybeObject* GetCode(PropertyType type, String* name);
    684 
    685   StrictModeFlag strict_mode_;
    686 };
    687 
    688 
    689 // Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
    690 // IC stubs.
    691 #define CUSTOM_CALL_IC_GENERATORS(V)            \
    692   V(ArrayPush)                                  \
    693   V(ArrayPop)                                   \
    694   V(StringCharCodeAt)                           \
    695   V(StringCharAt)                               \
    696   V(StringFromCharCode)                         \
    697   V(MathFloor)                                  \
    698   V(MathAbs)
    699 
    700 
    701 class CallOptimization;
    702 
    703 class CallStubCompiler: public StubCompiler {
    704  public:
    705   CallStubCompiler(int argc,
    706                    InLoopFlag in_loop,
    707                    Code::Kind kind,
    708                    Code::ExtraICState extra_ic_state,
    709                    InlineCacheHolderFlag cache_holder);
    710 
    711   MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
    712                                                 JSObject* holder,
    713                                                 int index,
    714                                                 String* name);
    715   MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
    716                                                    JSObject* holder,
    717                                                    JSFunction* function,
    718                                                    String* name,
    719                                                    CheckType check);
    720   MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
    721                                                       JSObject* holder,
    722                                                       String* name);
    723   MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
    724                                                  GlobalObject* holder,
    725                                                  JSGlobalPropertyCell* cell,
    726                                                  JSFunction* function,
    727                                                  String* name);
    728 
    729   static bool HasCustomCallGenerator(JSFunction* function);
    730 
    731  private:
    732   // Compiles a custom call constant/global IC. For constant calls
    733   // cell is NULL. Returns undefined if there is no custom call code
    734   // for the given function or it can't be generated.
    735   MUST_USE_RESULT MaybeObject* CompileCustomCall(Object* object,
    736                                                  JSObject* holder,
    737                                                  JSGlobalPropertyCell* cell,
    738                                                  JSFunction* function,
    739                                                  String* name);
    740 
    741 #define DECLARE_CALL_GENERATOR(name)                                           \
    742   MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object,             \
    743                                                    JSObject* holder,           \
    744                                                    JSGlobalPropertyCell* cell, \
    745                                                    JSFunction* function,       \
    746                                                    String* fname);
    747   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
    748 #undef DECLARE_CALL_GENERATOR
    749 
    750   MUST_USE_RESULT MaybeObject* CompileFastApiCall(
    751       const CallOptimization& optimization,
    752       Object* object,
    753       JSObject* holder,
    754       JSGlobalPropertyCell* cell,
    755       JSFunction* function,
    756       String* name);
    757 
    758   const ParameterCount arguments_;
    759   const InLoopFlag in_loop_;
    760   const Code::Kind kind_;
    761   const Code::ExtraICState extra_ic_state_;
    762   const InlineCacheHolderFlag cache_holder_;
    763 
    764   const ParameterCount& arguments() { return arguments_; }
    765 
    766   MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
    767 
    768   // Convenience function. Calls GetCode above passing
    769   // CONSTANT_FUNCTION type and the name of the given function.
    770   MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
    771 
    772   void GenerateNameCheck(String* name, Label* miss);
    773 
    774   void GenerateGlobalReceiverCheck(JSObject* object,
    775                                    JSObject* holder,
    776                                    String* name,
    777                                    Label* miss);
    778 
    779   // Generates code to load the function from the cell checking that
    780   // it still contains the same function.
    781   void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
    782                                     JSFunction* function,
    783                                     Label* miss);
    784 
    785   // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
    786   // be generated.
    787   MUST_USE_RESULT MaybeObject* GenerateMissBranch();
    788 };
    789 
    790 
    791 class ConstructStubCompiler: public StubCompiler {
    792  public:
    793   explicit ConstructStubCompiler() {}
    794 
    795   MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
    796 
    797  private:
    798   MaybeObject* GetCode();
    799 };
    800 
    801 
    802 // Holds information about possible function call optimizations.
    803 class CallOptimization BASE_EMBEDDED {
    804  public:
    805   explicit CallOptimization(LookupResult* lookup);
    806 
    807   explicit CallOptimization(JSFunction* function);
    808 
    809   bool is_constant_call() const {
    810     return constant_function_ != NULL;
    811   }
    812 
    813   JSFunction* constant_function() const {
    814     ASSERT(constant_function_ != NULL);
    815     return constant_function_;
    816   }
    817 
    818   bool is_simple_api_call() const {
    819     return is_simple_api_call_;
    820   }
    821 
    822   FunctionTemplateInfo* expected_receiver_type() const {
    823     ASSERT(is_simple_api_call_);
    824     return expected_receiver_type_;
    825   }
    826 
    827   CallHandlerInfo* api_call_info() const {
    828     ASSERT(is_simple_api_call_);
    829     return api_call_info_;
    830   }
    831 
    832   // Returns the depth of the object having the expected type in the
    833   // prototype chain between the two arguments.
    834   int GetPrototypeDepthOfExpectedType(JSObject* object,
    835                                       JSObject* holder) const;
    836 
    837  private:
    838   void Initialize(JSFunction* function);
    839 
    840   // Determines whether the given function can be called using the
    841   // fast api call builtin.
    842   void AnalyzePossibleApiFunction(JSFunction* function);
    843 
    844   JSFunction* constant_function_;
    845   bool is_simple_api_call_;
    846   FunctionTemplateInfo* expected_receiver_type_;
    847   CallHandlerInfo* api_call_info_;
    848 };
    849 
    850 class ExternalArrayStubCompiler: public StubCompiler {
    851  public:
    852   explicit ExternalArrayStubCompiler() {}
    853 
    854   MUST_USE_RESULT MaybeObject* CompileKeyedLoadStub(
    855       JSObject* receiver, ExternalArrayType array_type, Code::Flags flags);
    856 
    857   MUST_USE_RESULT MaybeObject* CompileKeyedStoreStub(
    858       JSObject* receiver, ExternalArrayType array_type, Code::Flags flags);
    859 
    860  private:
    861   MaybeObject* GetCode(Code::Flags flags);
    862 };
    863 
    864 } }  // namespace v8::internal
    865 
    866 #endif  // V8_STUB_CACHE_H_
    867