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 #include "v8.h"
     29 
     30 #include "api.h"
     31 #include "arguments.h"
     32 #include "ast.h"
     33 #include "code-stubs.h"
     34 #include "cpu-profiler.h"
     35 #include "gdb-jit.h"
     36 #include "ic-inl.h"
     37 #include "stub-cache.h"
     38 #include "vm-state-inl.h"
     39 
     40 namespace v8 {
     41 namespace internal {
     42 
     43 // -----------------------------------------------------------------------
     44 // StubCache implementation.
     45 
     46 
     47 StubCache::StubCache(Isolate* isolate)
     48     : isolate_(isolate) {
     49   ASSERT(isolate == Isolate::Current());
     50 }
     51 
     52 
     53 void StubCache::Initialize() {
     54   ASSERT(IsPowerOf2(kPrimaryTableSize));
     55   ASSERT(IsPowerOf2(kSecondaryTableSize));
     56   Clear();
     57 }
     58 
     59 
     60 Code* StubCache::Set(Name* name, Map* map, Code* code) {
     61   // Get the flags from the code.
     62   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
     63 
     64   // Validate that the name does not move on scavenge, and that we
     65   // can use identity checks instead of structural equality checks.
     66   ASSERT(!heap()->InNewSpace(name));
     67   ASSERT(name->IsUniqueName());
     68 
     69   // The state bits are not important to the hash function because
     70   // the stub cache only contains monomorphic stubs. Make sure that
     71   // the bits are the least significant so they will be the ones
     72   // masked out.
     73   ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
     74   STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
     75 
     76   // Make sure that the code type is not included in the hash.
     77   ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
     78 
     79   // Compute the primary entry.
     80   int primary_offset = PrimaryOffset(name, flags, map);
     81   Entry* primary = entry(primary_, primary_offset);
     82   Code* old_code = primary->value;
     83 
     84   // If the primary entry has useful data in it, we retire it to the
     85   // secondary cache before overwriting it.
     86   if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
     87     Map* old_map = primary->map;
     88     Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
     89     int seed = PrimaryOffset(primary->key, old_flags, old_map);
     90     int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
     91     Entry* secondary = entry(secondary_, secondary_offset);
     92     *secondary = *primary;
     93   }
     94 
     95   // Update primary cache.
     96   primary->key = name;
     97   primary->value = code;
     98   primary->map = map;
     99   isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
    100   return code;
    101 }
    102 
    103 
    104 Handle<JSObject> StubCache::StubHolder(Handle<JSObject> receiver,
    105                                        Handle<JSObject> holder) {
    106   InlineCacheHolderFlag cache_holder =
    107       IC::GetCodeCacheForObject(*receiver, *holder);
    108   return Handle<JSObject>(IC::GetCodeCacheHolder(
    109       isolate_, *receiver, cache_holder));
    110 }
    111 
    112 
    113 Handle<Code> StubCache::FindIC(Handle<Name> name,
    114                                Handle<Map> stub_holder_map,
    115                                Code::Kind kind,
    116                                Code::StubType type,
    117                                Code::ExtraICState extra_state) {
    118   Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state, type);
    119   Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags),
    120                        isolate_);
    121   if (probe->IsCode()) return Handle<Code>::cast(probe);
    122   return Handle<Code>::null();
    123 }
    124 
    125 
    126 Handle<Code> StubCache::FindIC(Handle<Name> name,
    127                                Handle<JSObject> stub_holder,
    128                                Code::Kind kind,
    129                                Code::StubType type,
    130                                Code::ExtraICState extra_ic_state) {
    131   return FindIC(name, Handle<Map>(stub_holder->map()), kind,
    132                 type, extra_ic_state);
    133 }
    134 
    135 
    136 Handle<Code> StubCache::FindLoadHandler(Handle<Name> name,
    137                                         Handle<JSObject> receiver,
    138                                         Handle<JSObject> stub_holder,
    139                                         Code::Kind kind,
    140                                         Code::StubType type) {
    141   Code::ExtraICState extra_ic_state = Code::ComputeExtraICState(
    142       receiver.is_identical_to(stub_holder) ? Code::OWN_STUB
    143                                             : Code::PROTOTYPE_STUB);
    144   ASSERT(type != Code::NORMAL);
    145   Code::Flags flags = Code::ComputeMonomorphicFlags(
    146       Code::STUB, extra_ic_state, type, kind);
    147   Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
    148                        isolate_);
    149   if (probe->IsCode()) return Handle<Code>::cast(probe);
    150   return Handle<Code>::null();
    151 }
    152 
    153 
    154 Handle<Code> StubCache::FindStoreHandler(Handle<Name> name,
    155                                          Handle<JSObject> receiver,
    156                                          Code::Kind kind,
    157                                          Code::StubType type,
    158                                          StrictModeFlag strict_mode) {
    159   Code::ExtraICState extra_ic_state = Code::ComputeExtraICState(
    160       STANDARD_STORE, strict_mode);
    161   ASSERT(type != Code::NORMAL);
    162   Code::Flags flags = Code::ComputeMonomorphicFlags(
    163       Code::STUB, extra_ic_state, type, kind);
    164   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
    165                        isolate_);
    166   if (probe->IsCode()) return Handle<Code>::cast(probe);
    167   return Handle<Code>::null();
    168 }
    169 
    170 
    171 Handle<Code> StubCache::ComputeMonomorphicLoadIC(Handle<JSObject> receiver,
    172                                                  Handle<Code> handler,
    173                                                  Handle<Name> name) {
    174   Handle<Code> ic = FindIC(name, receiver, Code::LOAD_IC, handler->type());
    175   if (!ic.is_null()) return ic;
    176 
    177   LoadStubCompiler ic_compiler(isolate());
    178   ic = ic_compiler.CompileMonomorphicIC(
    179       Handle<Map>(receiver->map()), handler, name);
    180 
    181   JSObject::UpdateMapCodeCache(receiver, name, ic);
    182   return ic;
    183 }
    184 
    185 
    186 Handle<Code> StubCache::ComputeMonomorphicKeyedLoadIC(Handle<JSObject> receiver,
    187                                                       Handle<Code> handler,
    188                                                       Handle<Name> name) {
    189   Handle<Code> ic = FindIC(
    190       name, receiver, Code::KEYED_LOAD_IC, handler->type());
    191   if (!ic.is_null()) return ic;
    192 
    193   KeyedLoadStubCompiler ic_compiler(isolate());
    194   ic = ic_compiler.CompileMonomorphicIC(
    195       Handle<Map>(receiver->map()), handler, name);
    196 
    197   JSObject::UpdateMapCodeCache(receiver, name, ic);
    198   return ic;
    199 }
    200 
    201 
    202 Handle<Code> StubCache::ComputeMonomorphicStoreIC(Handle<JSObject> receiver,
    203                                                   Handle<Code> handler,
    204                                                   Handle<Name> name,
    205                                                   StrictModeFlag strict_mode) {
    206   Handle<Code> ic = FindIC(
    207       name, receiver, Code::STORE_IC, handler->type(), strict_mode);
    208   if (!ic.is_null()) return ic;
    209 
    210   StoreStubCompiler ic_compiler(isolate(), strict_mode);
    211   ic = ic_compiler.CompileMonomorphicIC(
    212       Handle<Map>(receiver->map()), handler, name);
    213 
    214   JSObject::UpdateMapCodeCache(receiver, name, ic);
    215   return ic;
    216 }
    217 
    218 
    219 Handle<Code> StubCache::ComputeMonomorphicKeyedStoreIC(
    220     Handle<JSObject> receiver,
    221     Handle<Code> handler,
    222     Handle<Name> name,
    223     StrictModeFlag strict_mode) {
    224   Handle<Code> ic = FindIC(
    225       name, receiver, Code::KEYED_STORE_IC, handler->type(), strict_mode);
    226   if (!ic.is_null()) return ic;
    227 
    228   KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE);
    229   ic = ic_compiler.CompileMonomorphicIC(
    230       Handle<Map>(receiver->map()), handler, name);
    231 
    232   JSObject::UpdateMapCodeCache(receiver, name, ic);
    233   return ic;
    234 }
    235 
    236 
    237 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
    238                                                Handle<JSObject> receiver) {
    239   // If no global objects are present in the prototype chain, the load
    240   // nonexistent IC stub can be shared for all names for a given map
    241   // and we use the empty string for the map cache in that case.  If
    242   // there are global objects involved, we need to check global
    243   // property cells in the stub and therefore the stub will be
    244   // specific to the name.
    245   Handle<Name> cache_name = factory()->empty_string();
    246   Handle<JSObject> current;
    247   Handle<Object> next = receiver;
    248   Handle<GlobalObject> global;
    249   do {
    250     current = Handle<JSObject>::cast(next);
    251     next = Handle<Object>(current->GetPrototype(), isolate_);
    252     if (current->IsGlobalObject()) {
    253       global = Handle<GlobalObject>::cast(current);
    254       cache_name = name;
    255     } else if (!current->HasFastProperties()) {
    256       cache_name = name;
    257     }
    258   } while (!next->IsNull());
    259 
    260   // Compile the stub that is either shared for all names or
    261   // name specific if there are global objects involved.
    262   Handle<Code> handler = FindLoadHandler(
    263       cache_name, receiver, receiver, Code::LOAD_IC, Code::NONEXISTENT);
    264   if (!handler.is_null()) return handler;
    265 
    266   LoadStubCompiler compiler(isolate_);
    267   handler =
    268       compiler.CompileLoadNonexistent(receiver, current, cache_name, global);
    269   JSObject::UpdateMapCodeCache(receiver, cache_name, handler);
    270   return handler;
    271 }
    272 
    273 
    274 Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
    275                                          Handle<JSObject> receiver,
    276                                          Handle<JSObject> holder,
    277                                          PropertyIndex field,
    278                                          Representation representation) {
    279   if (receiver.is_identical_to(holder)) {
    280     LoadFieldStub stub(field.is_inobject(holder),
    281                        field.translate(holder),
    282                        representation);
    283     return stub.GetCode(isolate());
    284   }
    285 
    286   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    287   Handle<Code> stub = FindLoadHandler(
    288       name, receiver, stub_holder, Code::LOAD_IC, Code::FIELD);
    289   if (!stub.is_null()) return stub;
    290 
    291   LoadStubCompiler compiler(isolate_);
    292   Handle<Code> handler =
    293       compiler.CompileLoadField(receiver, holder, name, field, representation);
    294   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    295   return handler;
    296 }
    297 
    298 
    299 Handle<Code> StubCache::ComputeLoadCallback(
    300     Handle<Name> name,
    301     Handle<JSObject> receiver,
    302     Handle<JSObject> holder,
    303     Handle<ExecutableAccessorInfo> callback) {
    304   ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
    305   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    306   Handle<Code> stub = FindLoadHandler(
    307       name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
    308   if (!stub.is_null()) return stub;
    309 
    310   LoadStubCompiler compiler(isolate_);
    311   Handle<Code> handler =
    312       compiler.CompileLoadCallback(receiver, holder, name, callback);
    313   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    314   return handler;
    315 }
    316 
    317 
    318 Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
    319                                              Handle<JSObject> receiver,
    320                                              Handle<JSObject> holder,
    321                                              Handle<JSFunction> getter) {
    322   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    323   Handle<Code> stub = FindLoadHandler(
    324       name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
    325   if (!stub.is_null()) return stub;
    326 
    327   LoadStubCompiler compiler(isolate_);
    328   Handle<Code> handler =
    329       compiler.CompileLoadViaGetter(receiver, holder, name, getter);
    330   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    331   return handler;
    332 }
    333 
    334 
    335 Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
    336                                             Handle<JSObject> receiver,
    337                                             Handle<JSObject> holder,
    338                                             Handle<Object> value) {
    339   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    340   Handle<Code> handler = FindLoadHandler(
    341       name, receiver, stub_holder, Code::LOAD_IC, Code::CONSTANT);
    342   if (!handler.is_null()) return handler;
    343 
    344   LoadStubCompiler compiler(isolate_);
    345   handler = compiler.CompileLoadConstant(receiver, holder, name, value);
    346   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    347 
    348   return handler;
    349 }
    350 
    351 
    352 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
    353                                                Handle<JSObject> receiver,
    354                                                Handle<JSObject> holder) {
    355   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    356   Handle<Code> stub = FindLoadHandler(
    357       name, receiver, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
    358   if (!stub.is_null()) return stub;
    359 
    360   LoadStubCompiler compiler(isolate_);
    361   Handle<Code> handler =
    362         compiler.CompileLoadInterceptor(receiver, holder, name);
    363   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    364   return handler;
    365 }
    366 
    367 
    368 Handle<Code> StubCache::ComputeLoadNormal(Handle<Name> name,
    369                                           Handle<JSObject> receiver) {
    370   return isolate_->builtins()->LoadIC_Normal();
    371 }
    372 
    373 
    374 Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
    375                                           Handle<JSObject> receiver,
    376                                           Handle<GlobalObject> holder,
    377                                           Handle<PropertyCell> cell,
    378                                           bool is_dont_delete) {
    379   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    380   Handle<Code> stub = FindIC(name, stub_holder, Code::LOAD_IC, Code::NORMAL);
    381   if (!stub.is_null()) return stub;
    382 
    383   LoadStubCompiler compiler(isolate_);
    384   Handle<Code> ic =
    385       compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
    386   JSObject::UpdateMapCodeCache(stub_holder, name, ic);
    387   return ic;
    388 }
    389 
    390 
    391 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
    392                                               Handle<JSObject> receiver,
    393                                               Handle<JSObject> holder,
    394                                               PropertyIndex field,
    395                                               Representation representation) {
    396   if (receiver.is_identical_to(holder)) {
    397     // TODO(titzer): this should use an HObjectAccess
    398     KeyedLoadFieldStub stub(field.is_inobject(holder),
    399                             field.translate(holder),
    400                             representation);
    401     return stub.GetCode(isolate());
    402   }
    403 
    404   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    405   Handle<Code> stub = FindLoadHandler(
    406       name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
    407   if (!stub.is_null()) return stub;
    408 
    409   KeyedLoadStubCompiler compiler(isolate_);
    410   Handle<Code> handler =
    411       compiler.CompileLoadField(receiver, holder, name, field, representation);
    412   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    413   return handler;
    414 }
    415 
    416 
    417 Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
    418                                                  Handle<JSObject> receiver,
    419                                                  Handle<JSObject> holder,
    420                                                  Handle<Object> value) {
    421   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    422   Handle<Code> handler = FindLoadHandler(
    423       name, receiver, stub_holder, Code::KEYED_LOAD_IC,
    424       Code::CONSTANT);
    425   if (!handler.is_null()) return handler;
    426 
    427   KeyedLoadStubCompiler compiler(isolate_);
    428   handler = compiler.CompileLoadConstant(receiver, holder, name, value);
    429   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    430   return handler;
    431 }
    432 
    433 
    434 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
    435                                                     Handle<JSObject> receiver,
    436                                                     Handle<JSObject> holder) {
    437   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    438   Handle<Code> stub = FindLoadHandler(
    439       name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
    440   if (!stub.is_null()) return stub;
    441 
    442   KeyedLoadStubCompiler compiler(isolate_);
    443   Handle<Code> handler =
    444       compiler.CompileLoadInterceptor(receiver, holder, name);
    445   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    446   return handler;
    447 }
    448 
    449 
    450 Handle<Code> StubCache::ComputeKeyedLoadCallback(
    451     Handle<Name> name,
    452     Handle<JSObject> receiver,
    453     Handle<JSObject> holder,
    454     Handle<ExecutableAccessorInfo> callback) {
    455   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
    456   Handle<Code> stub = FindLoadHandler(
    457       name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
    458   if (!stub.is_null()) return stub;
    459 
    460   KeyedLoadStubCompiler compiler(isolate_);
    461   Handle<Code> handler =
    462       compiler.CompileLoadCallback(receiver, holder, name, callback);
    463   JSObject::UpdateMapCodeCache(stub_holder, name, handler);
    464   return handler;
    465 }
    466 
    467 
    468 Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
    469                                           Handle<JSObject> receiver,
    470                                           LookupResult* lookup,
    471                                           StrictModeFlag strict_mode) {
    472   Handle<Code> stub = FindStoreHandler(
    473       name, receiver, Code::STORE_IC, Code::FIELD, strict_mode);
    474   if (!stub.is_null()) return stub;
    475 
    476   StoreStubCompiler compiler(isolate_, strict_mode);
    477   Handle<Code> handler = compiler.CompileStoreField(receiver, lookup, name);
    478   JSObject::UpdateMapCodeCache(receiver, name, handler);
    479   return handler;
    480 }
    481 
    482 
    483 Handle<Code> StubCache::ComputeStoreTransition(Handle<Name> name,
    484                                                Handle<JSObject> receiver,
    485                                                LookupResult* lookup,
    486                                                Handle<Map> transition,
    487                                                StrictModeFlag strict_mode) {
    488   Handle<Code> stub = FindStoreHandler(
    489       name, receiver, Code::STORE_IC, Code::MAP_TRANSITION, strict_mode);
    490   if (!stub.is_null()) return stub;
    491 
    492   StoreStubCompiler compiler(isolate_, strict_mode);
    493   Handle<Code> handler =
    494       compiler.CompileStoreTransition(receiver, lookup, transition, name);
    495   JSObject::UpdateMapCodeCache(receiver, name, handler);
    496   return handler;
    497 }
    498 
    499 
    500 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
    501   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
    502   Handle<Name> name =
    503       isolate()->factory()->KeyedLoadElementMonomorphic_string();
    504 
    505   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
    506   if (probe->IsCode()) return Handle<Code>::cast(probe);
    507 
    508   KeyedLoadStubCompiler compiler(isolate());
    509   Handle<Code> code = compiler.CompileLoadElement(receiver_map);
    510 
    511   Map::UpdateCodeCache(receiver_map, name, code);
    512   return code;
    513 }
    514 
    515 
    516 Handle<Code> StubCache::ComputeKeyedStoreElement(
    517     Handle<Map> receiver_map,
    518     StrictModeFlag strict_mode,
    519     KeyedAccessStoreMode store_mode) {
    520   Code::ExtraICState extra_state =
    521       Code::ComputeExtraICState(store_mode, strict_mode);
    522   Code::Flags flags = Code::ComputeMonomorphicFlags(
    523       Code::KEYED_STORE_IC, extra_state);
    524 
    525   ASSERT(store_mode == STANDARD_STORE ||
    526          store_mode == STORE_AND_GROW_NO_TRANSITION ||
    527          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    528          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
    529 
    530   Handle<String> name =
    531       isolate()->factory()->KeyedStoreElementMonomorphic_string();
    532   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
    533   if (probe->IsCode()) return Handle<Code>::cast(probe);
    534 
    535   KeyedStoreStubCompiler compiler(isolate(), strict_mode, store_mode);
    536   Handle<Code> code = compiler.CompileStoreElement(receiver_map);
    537 
    538   Map::UpdateCodeCache(receiver_map, name, code);
    539   ASSERT(Code::GetKeyedAccessStoreMode(code->extra_ic_state()) == store_mode);
    540   return code;
    541 }
    542 
    543 
    544 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
    545   return (strict_mode == kStrictMode)
    546       ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
    547       : isolate_->builtins()->Builtins::StoreIC_Normal();
    548 }
    549 
    550 
    551 Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
    552                                            Handle<GlobalObject> receiver,
    553                                            Handle<PropertyCell> cell,
    554                                            Handle<Object> value,
    555                                            StrictModeFlag strict_mode) {
    556   Isolate* isolate = cell->GetIsolate();
    557   Handle<Type> union_type(PropertyCell::UpdateType(cell, value), isolate);
    558   bool is_constant = union_type->IsConstant();
    559   StoreGlobalStub stub(strict_mode, is_constant);
    560 
    561   Handle<Code> code = FindIC(
    562       name, Handle<JSObject>::cast(receiver),
    563       Code::STORE_IC, Code::NORMAL, stub.GetExtraICState());
    564   if (!code.is_null()) return code;
    565 
    566   // Replace the placeholder cell and global object map with the actual global
    567   // cell and receiver map.
    568   Handle<Map> meta_map(isolate_->heap()->meta_map());
    569   Handle<Object> receiver_map(receiver->map(), isolate_);
    570   code = stub.GetCodeCopyFromTemplate(isolate_);
    571   code->ReplaceNthObject(1, *meta_map, *receiver_map);
    572   Handle<Map> cell_map(isolate_->heap()->global_property_cell_map());
    573   code->ReplaceNthObject(1, *cell_map, *cell);
    574 
    575   JSObject::UpdateMapCodeCache(receiver, name, code);
    576 
    577   return code;
    578 }
    579 
    580 
    581 Handle<Code> StubCache::ComputeStoreCallback(
    582     Handle<Name> name,
    583     Handle<JSObject> receiver,
    584     Handle<JSObject> holder,
    585     Handle<ExecutableAccessorInfo> callback,
    586     StrictModeFlag strict_mode) {
    587   ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
    588   Handle<Code> stub = FindStoreHandler(
    589       name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
    590   if (!stub.is_null()) return stub;
    591 
    592   StoreStubCompiler compiler(isolate_, strict_mode);
    593   Handle<Code> handler = compiler.CompileStoreCallback(
    594       receiver, holder, name, callback);
    595   JSObject::UpdateMapCodeCache(receiver, name, handler);
    596   return handler;
    597 }
    598 
    599 
    600 Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
    601                                               Handle<JSObject> receiver,
    602                                               Handle<JSObject> holder,
    603                                               Handle<JSFunction> setter,
    604                                               StrictModeFlag strict_mode) {
    605   Handle<Code> stub = FindStoreHandler(
    606       name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
    607   if (!stub.is_null()) return stub;
    608 
    609   StoreStubCompiler compiler(isolate_, strict_mode);
    610   Handle<Code> handler = compiler.CompileStoreViaSetter(
    611       receiver, holder, name, setter);
    612   JSObject::UpdateMapCodeCache(receiver, name, handler);
    613   return handler;
    614 }
    615 
    616 
    617 Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
    618                                                 Handle<JSObject> receiver,
    619                                                 StrictModeFlag strict_mode) {
    620   Handle<Code> stub = FindStoreHandler(
    621       name, receiver, Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
    622   if (!stub.is_null()) return stub;
    623 
    624   StoreStubCompiler compiler(isolate_, strict_mode);
    625   Handle<Code> handler = compiler.CompileStoreInterceptor(receiver, name);
    626   JSObject::UpdateMapCodeCache(receiver, name, handler);
    627   return handler;
    628 }
    629 
    630 
    631 Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
    632                                                Handle<JSObject> receiver,
    633                                                LookupResult* lookup,
    634                                                StrictModeFlag strict_mode) {
    635   Handle<Code> stub = FindStoreHandler(
    636       name, receiver, Code::KEYED_STORE_IC, Code::FIELD, strict_mode);
    637   if (!stub.is_null()) return stub;
    638 
    639   KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
    640   Handle<Code> handler = compiler.CompileStoreField(receiver, lookup, name);
    641   JSObject::UpdateMapCodeCache(receiver, name, handler);
    642   return handler;
    643 }
    644 
    645 
    646 Handle<Code> StubCache::ComputeKeyedStoreTransition(
    647     Handle<Name> name,
    648     Handle<JSObject> receiver,
    649     LookupResult* lookup,
    650     Handle<Map> transition,
    651     StrictModeFlag strict_mode) {
    652   Handle<Code> stub = FindStoreHandler(
    653       name, receiver, Code::KEYED_STORE_IC, Code::MAP_TRANSITION, strict_mode);
    654   if (!stub.is_null()) return stub;
    655 
    656   KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
    657   Handle<Code> handler =
    658       compiler.CompileStoreTransition(receiver, lookup, transition, name);
    659   JSObject::UpdateMapCodeCache(receiver, name, handler);
    660   return handler;
    661 }
    662 
    663 
    664 #define CALL_LOGGER_TAG(kind, type) \
    665     (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
    666 
    667 Handle<Code> StubCache::ComputeCallConstant(int argc,
    668                                             Code::Kind kind,
    669                                             Code::ExtraICState extra_state,
    670                                             Handle<Name> name,
    671                                             Handle<Object> object,
    672                                             Handle<JSObject> holder,
    673                                             Handle<JSFunction> function) {
    674   // Compute the check type and the map.
    675   InlineCacheHolderFlag cache_holder =
    676       IC::GetCodeCacheForObject(*object, *holder);
    677   Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
    678       isolate_, *object, cache_holder));
    679 
    680   // Compute check type based on receiver/holder.
    681   CheckType check = RECEIVER_MAP_CHECK;
    682   if (object->IsString()) {
    683     check = STRING_CHECK;
    684   } else if (object->IsSymbol()) {
    685     check = SYMBOL_CHECK;
    686   } else if (object->IsNumber()) {
    687     check = NUMBER_CHECK;
    688   } else if (object->IsBoolean()) {
    689     check = BOOLEAN_CHECK;
    690   }
    691 
    692   if (check != RECEIVER_MAP_CHECK &&
    693       !function->IsBuiltin() &&
    694       function->shared()->is_classic_mode()) {
    695     // Calling non-strict non-builtins with a value as the receiver
    696     // requires boxing.
    697     return Handle<Code>::null();
    698   }
    699 
    700   Code::Flags flags = Code::ComputeMonomorphicFlags(
    701       kind, extra_state, Code::CONSTANT, argc, cache_holder);
    702   Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
    703                        isolate_);
    704   if (probe->IsCode()) return Handle<Code>::cast(probe);
    705 
    706   CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
    707   Handle<Code> code =
    708       compiler.CompileCallConstant(object, holder, name, check, function);
    709   code->set_check_type(check);
    710   ASSERT(flags == code->flags());
    711   PROFILE(isolate_,
    712           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
    713   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
    714 
    715   if (CallStubCompiler::CanBeCached(function)) {
    716     JSObject::UpdateMapCodeCache(stub_holder, name, code);
    717   }
    718   return code;
    719 }
    720 
    721 
    722 Handle<Code> StubCache::ComputeCallField(int argc,
    723                                          Code::Kind kind,
    724                                          Code::ExtraICState extra_state,
    725                                          Handle<Name> name,
    726                                          Handle<Object> object,
    727                                          Handle<JSObject> holder,
    728                                          PropertyIndex index) {
    729   // Compute the check type and the map.
    730   InlineCacheHolderFlag cache_holder =
    731       IC::GetCodeCacheForObject(*object, *holder);
    732   Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
    733       isolate_, *object, cache_holder));
    734 
    735   // TODO(1233596): We cannot do receiver map check for non-JS objects
    736   // because they may be represented as immediates without a
    737   // map. Instead, we check against the map in the holder.
    738   if (object->IsNumber() || object->IsSymbol() ||
    739       object->IsBoolean() || object->IsString()) {
    740     object = holder;
    741   }
    742 
    743   Code::Flags flags = Code::ComputeMonomorphicFlags(
    744       kind, extra_state, Code::FIELD, argc, cache_holder);
    745   Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
    746                        isolate_);
    747   if (probe->IsCode()) return Handle<Code>::cast(probe);
    748 
    749   CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
    750   Handle<Code> code =
    751       compiler.CompileCallField(Handle<JSObject>::cast(object),
    752                                 holder, index, name);
    753   ASSERT(flags == code->flags());
    754   PROFILE(isolate_,
    755           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
    756   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
    757   JSObject::UpdateMapCodeCache(stub_holder, name, code);
    758   return code;
    759 }
    760 
    761 
    762 Handle<Code> StubCache::ComputeCallInterceptor(int argc,
    763                                                Code::Kind kind,
    764                                                Code::ExtraICState extra_state,
    765                                                Handle<Name> name,
    766                                                Handle<Object> object,
    767                                                Handle<JSObject> holder) {
    768   // Compute the check type and the map.
    769   InlineCacheHolderFlag cache_holder =
    770       IC::GetCodeCacheForObject(*object, *holder);
    771   Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
    772       isolate_, *object, cache_holder));
    773 
    774   // TODO(1233596): We cannot do receiver map check for non-JS objects
    775   // because they may be represented as immediates without a
    776   // map. Instead, we check against the map in the holder.
    777   if (object->IsNumber() || object->IsSymbol() ||
    778       object->IsBoolean() || object->IsString()) {
    779     object = holder;
    780   }
    781 
    782   Code::Flags flags = Code::ComputeMonomorphicFlags(
    783       kind, extra_state, Code::INTERCEPTOR, argc, cache_holder);
    784   Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
    785                        isolate_);
    786   if (probe->IsCode()) return Handle<Code>::cast(probe);
    787 
    788   CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
    789   Handle<Code> code =
    790       compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
    791                                       holder, name);
    792   ASSERT(flags == code->flags());
    793   PROFILE(isolate(),
    794           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
    795   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
    796   JSObject::UpdateMapCodeCache(stub_holder, name, code);
    797   return code;
    798 }
    799 
    800 
    801 Handle<Code> StubCache::ComputeCallGlobal(int argc,
    802                                           Code::Kind kind,
    803                                           Code::ExtraICState extra_state,
    804                                           Handle<Name> name,
    805                                           Handle<JSObject> receiver,
    806                                           Handle<GlobalObject> holder,
    807                                           Handle<PropertyCell> cell,
    808                                           Handle<JSFunction> function) {
    809   InlineCacheHolderFlag cache_holder =
    810       IC::GetCodeCacheForObject(*receiver, *holder);
    811   Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
    812       isolate_, *receiver, cache_holder));
    813   Code::Flags flags = Code::ComputeMonomorphicFlags(
    814       kind, extra_state, Code::NORMAL, argc, cache_holder);
    815   Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
    816                        isolate_);
    817   if (probe->IsCode()) return Handle<Code>::cast(probe);
    818 
    819   CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
    820   Handle<Code> code =
    821       compiler.CompileCallGlobal(receiver, holder, cell, function, name);
    822   ASSERT(flags == code->flags());
    823   PROFILE(isolate(),
    824           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
    825   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
    826   if (CallStubCompiler::CanBeCached(function)) {
    827     JSObject::UpdateMapCodeCache(stub_holder, name, code);
    828   }
    829   return code;
    830 }
    831 
    832 
    833 static void FillCache(Isolate* isolate, Handle<Code> code) {
    834   Handle<UnseededNumberDictionary> dictionary =
    835       UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
    836                                     code->flags(),
    837                                     code);
    838   isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
    839 }
    840 
    841 
    842 Code* StubCache::FindCallInitialize(int argc,
    843                                     RelocInfo::Mode mode,
    844                                     Code::Kind kind) {
    845   Code::ExtraICState extra_state =
    846       CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
    847       CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
    848   Code::Flags flags =
    849       Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
    850   UnseededNumberDictionary* dictionary =
    851       isolate()->heap()->non_monomorphic_cache();
    852   int entry = dictionary->FindEntry(isolate(), flags);
    853   ASSERT(entry != -1);
    854   Object* code = dictionary->ValueAt(entry);
    855   // This might be called during the marking phase of the collector
    856   // hence the unchecked cast.
    857   return reinterpret_cast<Code*>(code);
    858 }
    859 
    860 
    861 Handle<Code> StubCache::ComputeCallInitialize(int argc,
    862                                               RelocInfo::Mode mode,
    863                                               Code::Kind kind) {
    864   Code::ExtraICState extra_state =
    865       CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
    866       CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
    867   Code::Flags flags =
    868       Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
    869   Handle<UnseededNumberDictionary> cache =
    870       isolate_->factory()->non_monomorphic_cache();
    871   int entry = cache->FindEntry(isolate_, flags);
    872   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
    873 
    874   StubCompiler compiler(isolate_);
    875   Handle<Code> code = compiler.CompileCallInitialize(flags);
    876   FillCache(isolate_, code);
    877   return code;
    878 }
    879 
    880 
    881 Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
    882   return ComputeCallInitialize(argc, mode, Code::CALL_IC);
    883 }
    884 
    885 
    886 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
    887   return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
    888                                Code::KEYED_CALL_IC);
    889 }
    890 
    891 
    892 Handle<Code> StubCache::ComputeCallPreMonomorphic(
    893     int argc,
    894     Code::Kind kind,
    895     Code::ExtraICState extra_state) {
    896   Code::Flags flags =
    897       Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
    898   Handle<UnseededNumberDictionary> cache =
    899       isolate_->factory()->non_monomorphic_cache();
    900   int entry = cache->FindEntry(isolate_, flags);
    901   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
    902 
    903   StubCompiler compiler(isolate_);
    904   Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
    905   FillCache(isolate_, code);
    906   return code;
    907 }
    908 
    909 
    910 Handle<Code> StubCache::ComputeCallNormal(int argc,
    911                                           Code::Kind kind,
    912                                           Code::ExtraICState extra_state) {
    913   Code::Flags flags =
    914       Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
    915   Handle<UnseededNumberDictionary> cache =
    916       isolate_->factory()->non_monomorphic_cache();
    917   int entry = cache->FindEntry(isolate_, flags);
    918   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
    919 
    920   StubCompiler compiler(isolate_);
    921   Handle<Code> code = compiler.CompileCallNormal(flags);
    922   FillCache(isolate_, code);
    923   return code;
    924 }
    925 
    926 
    927 Handle<Code> StubCache::ComputeCallArguments(int argc) {
    928   Code::Flags flags =
    929       Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
    930                          Code::kNoExtraICState, Code::NORMAL, argc);
    931   Handle<UnseededNumberDictionary> cache =
    932       isolate_->factory()->non_monomorphic_cache();
    933   int entry = cache->FindEntry(isolate_, flags);
    934   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
    935 
    936   StubCompiler compiler(isolate_);
    937   Handle<Code> code = compiler.CompileCallArguments(flags);
    938   FillCache(isolate_, code);
    939   return code;
    940 }
    941 
    942 
    943 Handle<Code> StubCache::ComputeCallMegamorphic(
    944     int argc,
    945     Code::Kind kind,
    946     Code::ExtraICState extra_state) {
    947   Code::Flags flags =
    948       Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
    949                          Code::NORMAL, argc);
    950   Handle<UnseededNumberDictionary> cache =
    951       isolate_->factory()->non_monomorphic_cache();
    952   int entry = cache->FindEntry(isolate_, flags);
    953   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
    954 
    955   StubCompiler compiler(isolate_);
    956   Handle<Code> code = compiler.CompileCallMegamorphic(flags);
    957   FillCache(isolate_, code);
    958   return code;
    959 }
    960 
    961 
    962 Handle<Code> StubCache::ComputeCallMiss(int argc,
    963                                         Code::Kind kind,
    964                                         Code::ExtraICState extra_state) {
    965   // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
    966   // and monomorphic stubs are not mixed up together in the stub cache.
    967   Code::Flags flags =
    968       Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
    969                          Code::NORMAL, argc, OWN_MAP);
    970   Handle<UnseededNumberDictionary> cache =
    971       isolate_->factory()->non_monomorphic_cache();
    972   int entry = cache->FindEntry(isolate_, flags);
    973   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
    974 
    975   StubCompiler compiler(isolate_);
    976   Handle<Code> code = compiler.CompileCallMiss(flags);
    977   FillCache(isolate_, code);
    978   return code;
    979 }
    980 
    981 
    982 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map,
    983                                           CompareNilICStub& stub) {
    984   Handle<String> name(isolate_->heap()->empty_string());
    985   if (!receiver_map->is_shared()) {
    986     Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC,
    987                                     Code::NORMAL, stub.GetExtraICState());
    988     if (!cached_ic.is_null()) return cached_ic;
    989   }
    990 
    991   Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_);
    992   ic->ReplaceNthObject(1, isolate_->heap()->meta_map(), *receiver_map);
    993 
    994   if (!receiver_map->is_shared()) {
    995     Map::UpdateCodeCache(receiver_map, name, ic);
    996   }
    997 
    998   return ic;
    999 }
   1000 
   1001 
   1002 Handle<Code> StubCache::ComputeLoadElementPolymorphic(
   1003     MapHandleList* receiver_maps) {
   1004   Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC);
   1005   Handle<PolymorphicCodeCache> cache =
   1006       isolate_->factory()->polymorphic_code_cache();
   1007   Handle<Object> probe = cache->Lookup(receiver_maps, flags);
   1008   if (probe->IsCode()) return Handle<Code>::cast(probe);
   1009 
   1010   CodeHandleList handlers(receiver_maps->length());
   1011   KeyedLoadStubCompiler compiler(isolate_);
   1012   compiler.CompileElementHandlers(receiver_maps, &handlers);
   1013   Handle<Code> code = compiler.CompilePolymorphicIC(
   1014       receiver_maps, &handlers, factory()->empty_string(),
   1015       Code::NORMAL, ELEMENT);
   1016 
   1017   isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
   1018 
   1019   PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
   1020   return code;
   1021 }
   1022 
   1023 
   1024 Handle<Code> StubCache::ComputePolymorphicLoadIC(MapHandleList* receiver_maps,
   1025                                                  CodeHandleList* handlers,
   1026                                                  int number_of_valid_maps,
   1027                                                  Handle<Name> name) {
   1028   LoadStubCompiler ic_compiler(isolate_);
   1029   Code::StubType type = number_of_valid_maps == 1 ? handlers->at(0)->type()
   1030                                                   : Code::NORMAL;
   1031   Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
   1032       receiver_maps, handlers, name, type, PROPERTY);
   1033   return ic;
   1034 }
   1035 
   1036 
   1037 Handle<Code> StubCache::ComputePolymorphicStoreIC(MapHandleList* receiver_maps,
   1038                                                   CodeHandleList* handlers,
   1039                                                   int number_of_valid_maps,
   1040                                                   Handle<Name> name,
   1041                                                   StrictModeFlag strict_mode) {
   1042   StoreStubCompiler ic_compiler(isolate_, strict_mode);
   1043   Code::StubType type = number_of_valid_maps == 1 ? handlers->at(0)->type()
   1044                                                   : Code::NORMAL;
   1045   Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
   1046       receiver_maps, handlers, name, type, PROPERTY);
   1047   return ic;
   1048 }
   1049 
   1050 
   1051 Handle<Code> StubCache::ComputeStoreElementPolymorphic(
   1052     MapHandleList* receiver_maps,
   1053     KeyedAccessStoreMode store_mode,
   1054     StrictModeFlag strict_mode) {
   1055   ASSERT(store_mode == STANDARD_STORE ||
   1056          store_mode == STORE_AND_GROW_NO_TRANSITION ||
   1057          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
   1058          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
   1059   Handle<PolymorphicCodeCache> cache =
   1060       isolate_->factory()->polymorphic_code_cache();
   1061   Code::ExtraICState extra_state = Code::ComputeExtraICState(store_mode,
   1062                                                              strict_mode);
   1063   Code::Flags flags =
   1064       Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state);
   1065   Handle<Object> probe = cache->Lookup(receiver_maps, flags);
   1066   if (probe->IsCode()) return Handle<Code>::cast(probe);
   1067 
   1068   KeyedStoreStubCompiler compiler(isolate_, strict_mode, store_mode);
   1069   Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps);
   1070   PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
   1071   return code;
   1072 }
   1073 
   1074 
   1075 #ifdef ENABLE_DEBUGGER_SUPPORT
   1076 Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
   1077                                               Code::Kind kind) {
   1078   // Extra IC state is irrelevant for debug break ICs. They jump to
   1079   // the actual call ic to carry out the work.
   1080   Code::Flags flags =
   1081       Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK,
   1082                          Code::NORMAL, argc);
   1083   Handle<UnseededNumberDictionary> cache =
   1084       isolate_->factory()->non_monomorphic_cache();
   1085   int entry = cache->FindEntry(isolate_, flags);
   1086   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
   1087 
   1088   StubCompiler compiler(isolate_);
   1089   Handle<Code> code = compiler.CompileCallDebugBreak(flags);
   1090   FillCache(isolate_, code);
   1091   return code;
   1092 }
   1093 
   1094 
   1095 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
   1096                                                       Code::Kind kind) {
   1097   // Extra IC state is irrelevant for debug break ICs. They jump to
   1098   // the actual call ic to carry out the work.
   1099   Code::Flags flags =
   1100       Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN,
   1101                          Code::NORMAL, argc);
   1102   Handle<UnseededNumberDictionary> cache =
   1103       isolate_->factory()->non_monomorphic_cache();
   1104   int entry = cache->FindEntry(isolate_, flags);
   1105   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
   1106 
   1107   StubCompiler compiler(isolate_);
   1108   Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
   1109   FillCache(isolate_, code);
   1110   return code;
   1111 }
   1112 #endif
   1113 
   1114 
   1115 void StubCache::Clear() {
   1116   Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
   1117   for (int i = 0; i < kPrimaryTableSize; i++) {
   1118     primary_[i].key = heap()->empty_string();
   1119     primary_[i].map = NULL;
   1120     primary_[i].value = empty;
   1121   }
   1122   for (int j = 0; j < kSecondaryTableSize; j++) {
   1123     secondary_[j].key = heap()->empty_string();
   1124     secondary_[j].map = NULL;
   1125     secondary_[j].value = empty;
   1126   }
   1127 }
   1128 
   1129 
   1130 void StubCache::CollectMatchingMaps(SmallMapList* types,
   1131                                     Handle<Name> name,
   1132                                     Code::Flags flags,
   1133                                     Handle<Context> native_context,
   1134                                     Zone* zone) {
   1135   for (int i = 0; i < kPrimaryTableSize; i++) {
   1136     if (primary_[i].key == *name) {
   1137       Map* map = primary_[i].map;
   1138       // Map can be NULL, if the stub is constant function call
   1139       // with a primitive receiver.
   1140       if (map == NULL) continue;
   1141 
   1142       int offset = PrimaryOffset(*name, flags, map);
   1143       if (entry(primary_, offset) == &primary_[i] &&
   1144           !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
   1145         types->AddMapIfMissing(Handle<Map>(map), zone);
   1146       }
   1147     }
   1148   }
   1149 
   1150   for (int i = 0; i < kSecondaryTableSize; i++) {
   1151     if (secondary_[i].key == *name) {
   1152       Map* map = secondary_[i].map;
   1153       // Map can be NULL, if the stub is constant function call
   1154       // with a primitive receiver.
   1155       if (map == NULL) continue;
   1156 
   1157       // Lookup in primary table and skip duplicates.
   1158       int primary_offset = PrimaryOffset(*name, flags, map);
   1159 
   1160       // Lookup in secondary table and add matches.
   1161       int offset = SecondaryOffset(*name, flags, primary_offset);
   1162       if (entry(secondary_, offset) == &secondary_[i] &&
   1163           !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
   1164         types->AddMapIfMissing(Handle<Map>(map), zone);
   1165       }
   1166     }
   1167   }
   1168 }
   1169 
   1170 
   1171 // ------------------------------------------------------------------------
   1172 // StubCompiler implementation.
   1173 
   1174 
   1175 RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
   1176   JSObject* recv = JSObject::cast(args[0]);
   1177   ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]);
   1178   Address setter_address = v8::ToCData<Address>(callback->setter());
   1179   v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
   1180   ASSERT(fun != NULL);
   1181   ASSERT(callback->IsCompatibleReceiver(recv));
   1182   Handle<Name> name = args.at<Name>(2);
   1183   Handle<Object> value = args.at<Object>(3);
   1184   HandleScope scope(isolate);
   1185 
   1186   // TODO(rossberg): Support symbols in the API.
   1187   if (name->IsSymbol()) return *value;
   1188   Handle<String> str = Handle<String>::cast(name);
   1189 
   1190   LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
   1191   PropertyCallbackArguments
   1192       custom_args(isolate, callback->data(), recv, recv);
   1193   custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value));
   1194   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1195   return *value;
   1196 }
   1197 
   1198 
   1199 static const int kAccessorInfoOffsetInInterceptorArgs = 2;
   1200 
   1201 
   1202 /**
   1203  * Attempts to load a property with an interceptor (which must be present),
   1204  * but doesn't search the prototype chain.
   1205  *
   1206  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
   1207  * provide any value for the given name.
   1208  */
   1209 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
   1210   typedef PropertyCallbackArguments PCA;
   1211   static const int kArgsOffset = kAccessorInfoOffsetInInterceptorArgs;
   1212   Handle<Name> name_handle = args.at<Name>(0);
   1213   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
   1214   ASSERT(kArgsOffset == 2);
   1215   // No ReturnValue in interceptors.
   1216   ASSERT_EQ(kArgsOffset + PCA::kArgsLength - 2, args.length());
   1217 
   1218   // TODO(rossberg): Support symbols in the API.
   1219   if (name_handle->IsSymbol())
   1220     return isolate->heap()->no_interceptor_result_sentinel();
   1221   Handle<String> name = Handle<String>::cast(name_handle);
   1222 
   1223   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
   1224   v8::NamedPropertyGetter getter =
   1225       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
   1226   ASSERT(getter != NULL);
   1227 
   1228   Handle<JSObject> receiver =
   1229       args.at<JSObject>(kArgsOffset - PCA::kThisIndex);
   1230   Handle<JSObject> holder =
   1231       args.at<JSObject>(kArgsOffset - PCA::kHolderIndex);
   1232   PropertyCallbackArguments callback_args(isolate,
   1233                                           interceptor_info->data(),
   1234                                           *receiver,
   1235                                           *holder);
   1236   {
   1237     // Use the interceptor getter.
   1238     HandleScope scope(isolate);
   1239     v8::Handle<v8::Value> r =
   1240         callback_args.Call(getter, v8::Utils::ToLocal(name));
   1241     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1242     if (!r.IsEmpty()) {
   1243       Handle<Object> result = v8::Utils::OpenHandle(*r);
   1244       result->VerifyApiCallResultType();
   1245       return *v8::Utils::OpenHandle(*r);
   1246     }
   1247   }
   1248 
   1249   return isolate->heap()->no_interceptor_result_sentinel();
   1250 }
   1251 
   1252 
   1253 static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
   1254   // If the load is non-contextual, just return the undefined result.
   1255   // Note that both keyed and non-keyed loads may end up here, so we
   1256   // can't use either LoadIC or KeyedLoadIC constructors.
   1257   IC ic(IC::NO_EXTRA_FRAME, isolate);
   1258   ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
   1259   if (!ic.SlowIsUndeclaredGlobal()) return HEAP->undefined_value();
   1260 
   1261   // Throw a reference error.
   1262   HandleScope scope(isolate);
   1263   Handle<Name> name_handle(name);
   1264   Handle<Object> error =
   1265       isolate->factory()->NewReferenceError("not_defined",
   1266                                             HandleVector(&name_handle, 1));
   1267   return isolate->Throw(*error);
   1268 }
   1269 
   1270 
   1271 static MaybeObject* LoadWithInterceptor(Arguments* args,
   1272                                         PropertyAttributes* attrs) {
   1273   typedef PropertyCallbackArguments PCA;
   1274   static const int kArgsOffset = kAccessorInfoOffsetInInterceptorArgs;
   1275   Handle<Name> name_handle = args->at<Name>(0);
   1276   Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
   1277   ASSERT(kArgsOffset == 2);
   1278   // No ReturnValue in interceptors.
   1279   ASSERT_EQ(kArgsOffset + PCA::kArgsLength - 2, args->length());
   1280   Handle<JSObject> receiver_handle =
   1281       args->at<JSObject>(kArgsOffset - PCA::kThisIndex);
   1282   Handle<JSObject> holder_handle =
   1283       args->at<JSObject>(kArgsOffset - PCA::kHolderIndex);
   1284 
   1285   Isolate* isolate = receiver_handle->GetIsolate();
   1286 
   1287   // TODO(rossberg): Support symbols in the API.
   1288   if (name_handle->IsSymbol())
   1289     return holder_handle->GetPropertyPostInterceptor(
   1290         *receiver_handle, *name_handle, attrs);
   1291   Handle<String> name = Handle<String>::cast(name_handle);
   1292 
   1293   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
   1294   v8::NamedPropertyGetter getter =
   1295       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
   1296   ASSERT(getter != NULL);
   1297 
   1298   PropertyCallbackArguments callback_args(isolate,
   1299                                           interceptor_info->data(),
   1300                                           *receiver_handle,
   1301                                           *holder_handle);
   1302   {
   1303     // Use the interceptor getter.
   1304     HandleScope scope(isolate);
   1305     v8::Handle<v8::Value> r =
   1306         callback_args.Call(getter, v8::Utils::ToLocal(name));
   1307     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1308     if (!r.IsEmpty()) {
   1309       *attrs = NONE;
   1310       Handle<Object> result = v8::Utils::OpenHandle(*r);
   1311       result->VerifyApiCallResultType();
   1312       return *result;
   1313     }
   1314   }
   1315 
   1316   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
   1317       *receiver_handle,
   1318       *name_handle,
   1319       attrs);
   1320   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1321   return result;
   1322 }
   1323 
   1324 
   1325 /**
   1326  * Loads a property with an interceptor performing post interceptor
   1327  * lookup if interceptor failed.
   1328  */
   1329 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
   1330   PropertyAttributes attr = NONE;
   1331   Object* result;
   1332   { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
   1333     if (!maybe_result->ToObject(&result)) return maybe_result;
   1334   }
   1335 
   1336   // If the property is present, return it.
   1337   if (attr != ABSENT) return result;
   1338   return ThrowReferenceError(isolate, Name::cast(args[0]));
   1339 }
   1340 
   1341 
   1342 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
   1343   PropertyAttributes attr;
   1344   MaybeObject* result = LoadWithInterceptor(&args, &attr);
   1345   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1346   // This is call IC. In this case, we simply return the undefined result which
   1347   // will lead to an exception when trying to invoke the result as a
   1348   // function.
   1349   return result;
   1350 }
   1351 
   1352 
   1353 RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
   1354   ASSERT(args.length() == 4);
   1355   JSObject* recv = JSObject::cast(args[0]);
   1356   Name* name = Name::cast(args[1]);
   1357   Object* value = args[2];
   1358   ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
   1359   StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
   1360   ASSERT(recv->HasNamedInterceptor());
   1361   PropertyAttributes attr = NONE;
   1362   MaybeObject* result = recv->SetPropertyWithInterceptor(
   1363       name, value, attr, strict_mode);
   1364   return result;
   1365 }
   1366 
   1367 
   1368 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
   1369   JSObject* receiver = JSObject::cast(args[0]);
   1370   ASSERT(args.smi_at(1) >= 0);
   1371   uint32_t index = args.smi_at(1);
   1372   return receiver->GetElementWithInterceptor(receiver, index);
   1373 }
   1374 
   1375 
   1376 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
   1377   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1378   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   1379   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   1380   if (kind == Code::CALL_IC) {
   1381     CallIC::GenerateInitialize(masm(), argc, extra_state);
   1382   } else {
   1383     KeyedCallIC::GenerateInitialize(masm(), argc);
   1384   }
   1385   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
   1386   isolate()->counters()->call_initialize_stubs()->Increment();
   1387   PROFILE(isolate(),
   1388           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
   1389                           *code, code->arguments_count()));
   1390   GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
   1391   return code;
   1392 }
   1393 
   1394 
   1395 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
   1396   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1397   // The code of the PreMonomorphic stub is the same as the code
   1398   // of the Initialized stub.  They just differ on the code object flags.
   1399   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   1400   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   1401   if (kind == Code::CALL_IC) {
   1402     CallIC::GenerateInitialize(masm(), argc, extra_state);
   1403   } else {
   1404     KeyedCallIC::GenerateInitialize(masm(), argc);
   1405   }
   1406   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
   1407   isolate()->counters()->call_premonomorphic_stubs()->Increment();
   1408   PROFILE(isolate(),
   1409           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
   1410                           *code, code->arguments_count()));
   1411   GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
   1412   return code;
   1413 }
   1414 
   1415 
   1416 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
   1417   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1418   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   1419   if (kind == Code::CALL_IC) {
   1420     // Call normal is always with a explict receiver.
   1421     ASSERT(!CallIC::Contextual::decode(
   1422         Code::ExtractExtraICStateFromFlags(flags)));
   1423     CallIC::GenerateNormal(masm(), argc);
   1424   } else {
   1425     KeyedCallIC::GenerateNormal(masm(), argc);
   1426   }
   1427   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
   1428   isolate()->counters()->call_normal_stubs()->Increment();
   1429   PROFILE(isolate(),
   1430           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
   1431                           *code, code->arguments_count()));
   1432   GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
   1433   return code;
   1434 }
   1435 
   1436 
   1437 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
   1438   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1439   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   1440   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   1441   if (kind == Code::CALL_IC) {
   1442     CallIC::GenerateMegamorphic(masm(), argc, extra_state);
   1443   } else {
   1444     KeyedCallIC::GenerateMegamorphic(masm(), argc);
   1445   }
   1446   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
   1447   isolate()->counters()->call_megamorphic_stubs()->Increment();
   1448   PROFILE(isolate(),
   1449           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
   1450                           *code, code->arguments_count()));
   1451   GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
   1452   return code;
   1453 }
   1454 
   1455 
   1456 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
   1457   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1458   KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
   1459   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
   1460   PROFILE(isolate(),
   1461           CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
   1462                                           CALL_MEGAMORPHIC_TAG),
   1463                           *code, code->arguments_count()));
   1464   GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
   1465   return code;
   1466 }
   1467 
   1468 
   1469 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
   1470   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1471   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   1472   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   1473   if (kind == Code::CALL_IC) {
   1474     CallIC::GenerateMiss(masm(), argc, extra_state);
   1475   } else {
   1476     KeyedCallIC::GenerateMiss(masm(), argc);
   1477   }
   1478   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
   1479   isolate()->counters()->call_megamorphic_stubs()->Increment();
   1480   PROFILE(isolate(),
   1481           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
   1482                           *code, code->arguments_count()));
   1483   GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
   1484   return code;
   1485 }
   1486 
   1487 
   1488 #ifdef ENABLE_DEBUGGER_SUPPORT
   1489 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
   1490   Debug::GenerateCallICDebugBreak(masm());
   1491   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
   1492   PROFILE(isolate(),
   1493           CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
   1494                                           CALL_DEBUG_BREAK_TAG),
   1495                           *code, code->arguments_count()));
   1496   return code;
   1497 }
   1498 
   1499 
   1500 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
   1501   // Use the same code for the the step in preparations as we do for the
   1502   // miss case.
   1503   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1504   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   1505   if (kind == Code::CALL_IC) {
   1506     // For the debugger extra ic state is irrelevant.
   1507     CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
   1508   } else {
   1509     KeyedCallIC::GenerateMiss(masm(), argc);
   1510   }
   1511   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
   1512   PROFILE(isolate(),
   1513           CodeCreateEvent(
   1514               CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
   1515               *code,
   1516               code->arguments_count()));
   1517   return code;
   1518 }
   1519 #endif  // ENABLE_DEBUGGER_SUPPORT
   1520 
   1521 #undef CALL_LOGGER_TAG
   1522 
   1523 
   1524 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
   1525                                             const char* name) {
   1526   // Create code object in the heap.
   1527   CodeDesc desc;
   1528   masm_.GetCode(&desc);
   1529   Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
   1530 #ifdef ENABLE_DISASSEMBLER
   1531   if (FLAG_print_code_stubs) code->Disassemble(name);
   1532 #endif
   1533   return code;
   1534 }
   1535 
   1536 
   1537 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
   1538                                             Handle<Name> name) {
   1539   return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
   1540       ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString())
   1541       : GetCodeWithFlags(flags, NULL);
   1542 }
   1543 
   1544 
   1545 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
   1546                                          Handle<Name> name,
   1547                                          LookupResult* lookup) {
   1548   holder->LocalLookupRealNamedProperty(*name, lookup);
   1549   if (lookup->IsFound()) return;
   1550   if (holder->GetPrototype()->IsNull()) return;
   1551   holder->GetPrototype()->Lookup(*name, lookup);
   1552 }
   1553 
   1554 
   1555 #define __ ACCESS_MASM(masm())
   1556 
   1557 
   1558 Register BaseLoadStubCompiler::HandlerFrontendHeader(
   1559     Handle<JSObject> object,
   1560     Register object_reg,
   1561     Handle<JSObject> holder,
   1562     Handle<Name> name,
   1563     Label* miss) {
   1564   return CheckPrototypes(object, object_reg, holder,
   1565                          scratch1(), scratch2(), scratch3(),
   1566                          name, miss, SKIP_RECEIVER);
   1567 }
   1568 
   1569 
   1570 // HandlerFrontend for store uses the name register. It has to be restored
   1571 // before a miss.
   1572 Register BaseStoreStubCompiler::HandlerFrontendHeader(
   1573     Handle<JSObject> object,
   1574     Register object_reg,
   1575     Handle<JSObject> holder,
   1576     Handle<Name> name,
   1577     Label* miss) {
   1578   return CheckPrototypes(object, object_reg, holder,
   1579                          this->name(), scratch1(), scratch2(),
   1580                          name, miss, SKIP_RECEIVER);
   1581 }
   1582 
   1583 
   1584 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object,
   1585                                                     Register object_reg,
   1586                                                     Handle<JSObject> holder,
   1587                                                     Handle<Name> name,
   1588                                                     Label* success) {
   1589   Label miss;
   1590 
   1591   Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
   1592 
   1593   HandlerFrontendFooter(name, success, &miss);
   1594   return reg;
   1595 }
   1596 
   1597 
   1598 Handle<Code> BaseLoadStubCompiler::CompileLoadField(
   1599     Handle<JSObject> object,
   1600     Handle<JSObject> holder,
   1601     Handle<Name> name,
   1602     PropertyIndex field,
   1603     Representation representation) {
   1604   Label miss;
   1605 
   1606   Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss);
   1607 
   1608   GenerateLoadField(reg, holder, field, representation);
   1609 
   1610   __ bind(&miss);
   1611   TailCallBuiltin(masm(), MissBuiltin(kind()));
   1612 
   1613   // Return the generated code.
   1614   return GetCode(kind(), Code::FIELD, name);
   1615 }
   1616 
   1617 
   1618 Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
   1619     Handle<JSObject> object,
   1620     Handle<JSObject> holder,
   1621     Handle<Name> name,
   1622     Handle<Object> value) {
   1623   Label success;
   1624   HandlerFrontend(object, receiver(), holder, name, &success);
   1625   __ bind(&success);
   1626   GenerateLoadConstant(value);
   1627 
   1628   // Return the generated code.
   1629   return GetCode(kind(), Code::CONSTANT, name);
   1630 }
   1631 
   1632 
   1633 Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
   1634     Handle<JSObject> object,
   1635     Handle<JSObject> holder,
   1636     Handle<Name> name,
   1637     Handle<ExecutableAccessorInfo> callback) {
   1638   Label success;
   1639 
   1640   Register reg = CallbackHandlerFrontend(
   1641       object, receiver(), holder, name, &success, callback);
   1642   __ bind(&success);
   1643   GenerateLoadCallback(reg, callback);
   1644 
   1645   // Return the generated code.
   1646   return GetCode(kind(), Code::CALLBACKS, name);
   1647 }
   1648 
   1649 
   1650 Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
   1651     Handle<JSObject> object,
   1652     Handle<JSObject> holder,
   1653     Handle<Name> name) {
   1654   Label success;
   1655 
   1656   LookupResult lookup(isolate());
   1657   LookupPostInterceptor(holder, name, &lookup);
   1658 
   1659   Register reg = HandlerFrontend(object, receiver(), holder, name, &success);
   1660   __ bind(&success);
   1661   // TODO(368): Compile in the whole chain: all the interceptors in
   1662   // prototypes and ultimate answer.
   1663   GenerateLoadInterceptor(reg, object, holder, &lookup, name);
   1664 
   1665   // Return the generated code.
   1666   return GetCode(kind(), Code::INTERCEPTOR, name);
   1667 }
   1668 
   1669 
   1670 void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
   1671     Register interceptor_reg,
   1672     Handle<JSObject> interceptor_holder,
   1673     Handle<Name> name,
   1674     LookupResult* lookup) {
   1675   Label success;
   1676   Handle<JSObject> holder(lookup->holder());
   1677   if (lookup->IsField()) {
   1678     PropertyIndex field = lookup->GetFieldIndex();
   1679     if (interceptor_holder.is_identical_to(holder)) {
   1680       GenerateLoadField(
   1681           interceptor_reg, holder, field, lookup->representation());
   1682     } else {
   1683       // We found FIELD property in prototype chain of interceptor's holder.
   1684       // Retrieve a field from field's holder.
   1685       Register reg = HandlerFrontend(
   1686           interceptor_holder, interceptor_reg, holder, name, &success);
   1687       __ bind(&success);
   1688       GenerateLoadField(
   1689           reg, holder, field, lookup->representation());
   1690     }
   1691   } else {
   1692     // We found CALLBACKS property in prototype chain of interceptor's
   1693     // holder.
   1694     ASSERT(lookup->type() == CALLBACKS);
   1695     Handle<ExecutableAccessorInfo> callback(
   1696         ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
   1697     ASSERT(callback->getter() != NULL);
   1698 
   1699     Register reg = CallbackHandlerFrontend(
   1700         interceptor_holder, interceptor_reg, holder, name, &success, callback);
   1701     __ bind(&success);
   1702     GenerateLoadCallback(reg, callback);
   1703   }
   1704 }
   1705 
   1706 
   1707 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC(
   1708     Handle<Map> receiver_map,
   1709     Handle<Code> handler,
   1710     Handle<Name> name) {
   1711   MapHandleList receiver_maps(1);
   1712   receiver_maps.Add(receiver_map);
   1713   CodeHandleList handlers(1);
   1714   handlers.Add(handler);
   1715   Code::StubType type = handler->type();
   1716   return CompilePolymorphicIC(&receiver_maps, &handlers, name, type, PROPERTY);
   1717 }
   1718 
   1719 
   1720 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
   1721     Handle<JSObject> object,
   1722     Handle<JSObject> holder,
   1723     Handle<Name> name,
   1724     Handle<JSFunction> getter) {
   1725   Label success;
   1726   HandlerFrontend(object, receiver(), holder, name, &success);
   1727 
   1728   __ bind(&success);
   1729   GenerateLoadViaGetter(masm(), getter);
   1730 
   1731   // Return the generated code.
   1732   return GetCode(kind(), Code::CALLBACKS, name);
   1733 }
   1734 
   1735 
   1736 Handle<Code> BaseStoreStubCompiler::CompileStoreTransition(
   1737     Handle<JSObject> object,
   1738     LookupResult* lookup,
   1739     Handle<Map> transition,
   1740     Handle<Name> name) {
   1741   Label miss, slow;
   1742 
   1743   // Ensure no transitions to deprecated maps are followed.
   1744   __ CheckMapDeprecated(transition, scratch1(), &miss);
   1745 
   1746   // Check that we are allowed to write this.
   1747   if (object->GetPrototype()->IsJSObject()) {
   1748     Handle<JSObject> holder;
   1749     // holder == object indicates that no property was found.
   1750     if (lookup->holder() != *object) {
   1751       holder = Handle<JSObject>(lookup->holder());
   1752     } else {
   1753       // Find the top object.
   1754       holder = object;
   1755       do {
   1756         holder = Handle<JSObject>(JSObject::cast(holder->GetPrototype()));
   1757       } while (holder->GetPrototype()->IsJSObject());
   1758     }
   1759 
   1760     Register holder_reg =
   1761         HandlerFrontendHeader(object, receiver(), holder, name, &miss);
   1762 
   1763     // If no property was found, and the holder (the last object in the
   1764     // prototype chain) is in slow mode, we need to do a negative lookup on the
   1765     // holder.
   1766     if (lookup->holder() == *object) {
   1767       GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss);
   1768     }
   1769   }
   1770 
   1771   GenerateStoreTransition(masm(),
   1772                           object,
   1773                           lookup,
   1774                           transition,
   1775                           name,
   1776                           receiver(), this->name(), value(),
   1777                           scratch1(), scratch2(), scratch3(),
   1778                           &miss,
   1779                           &slow);
   1780 
   1781   // Handle store cache miss.
   1782   GenerateRestoreName(masm(), &miss, name);
   1783   TailCallBuiltin(masm(), MissBuiltin(kind()));
   1784 
   1785   GenerateRestoreName(masm(), &slow, name);
   1786   TailCallBuiltin(masm(), SlowBuiltin(kind()));
   1787 
   1788   // Return the generated code.
   1789   return GetCode(kind(), Code::MAP_TRANSITION, name);
   1790 }
   1791 
   1792 
   1793 Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
   1794                                                       LookupResult* lookup,
   1795                                                       Handle<Name> name) {
   1796   Label miss;
   1797 
   1798   HandlerFrontendHeader(object, receiver(), object, name, &miss);
   1799 
   1800   // Generate store field code.
   1801   GenerateStoreField(masm(),
   1802                      object,
   1803                      lookup,
   1804                      receiver(), this->name(), value(), scratch1(), scratch2(),
   1805                      &miss);
   1806 
   1807   // Handle store cache miss.
   1808   __ bind(&miss);
   1809   TailCallBuiltin(masm(), MissBuiltin(kind()));
   1810 
   1811   // Return the generated code.
   1812   return GetCode(kind(), Code::FIELD, name);
   1813 }
   1814 
   1815 
   1816 Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
   1817     Handle<JSObject> object,
   1818     Handle<JSObject> holder,
   1819     Handle<Name> name,
   1820     Handle<JSFunction> setter) {
   1821   Label success;
   1822   HandlerFrontend(object, receiver(), holder, name, &success);
   1823 
   1824   __ bind(&success);
   1825   GenerateStoreViaSetter(masm(), setter);
   1826 
   1827   return GetCode(kind(), Code::CALLBACKS, name);
   1828 }
   1829 
   1830 
   1831 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
   1832     Handle<Map> receiver_map) {
   1833   ElementsKind elements_kind = receiver_map->elements_kind();
   1834   if (receiver_map->has_fast_elements() ||
   1835       receiver_map->has_external_array_elements()) {
   1836     Handle<Code> stub = KeyedLoadFastElementStub(
   1837         receiver_map->instance_type() == JS_ARRAY_TYPE,
   1838         elements_kind).GetCode(isolate());
   1839     __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
   1840   } else {
   1841     Handle<Code> stub =
   1842         KeyedLoadDictionaryElementStub().GetCode(isolate());
   1843     __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
   1844   }
   1845 
   1846   TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
   1847 
   1848   // Return the generated code.
   1849   return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
   1850 }
   1851 
   1852 
   1853 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
   1854     Handle<Map> receiver_map) {
   1855   ElementsKind elements_kind = receiver_map->elements_kind();
   1856   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
   1857   Handle<Code> stub;
   1858   if (FLAG_compiled_keyed_stores &&
   1859       (receiver_map->has_fast_elements() ||
   1860        receiver_map->has_external_array_elements())) {
   1861     stub = KeyedStoreFastElementStub(
   1862         is_jsarray,
   1863         elements_kind,
   1864         store_mode_).GetCode(isolate());
   1865   } else {
   1866     stub = KeyedStoreElementStub(is_jsarray,
   1867                                  elements_kind,
   1868                                  store_mode_).GetCode(isolate());
   1869   }
   1870 
   1871   __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
   1872 
   1873   TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
   1874 
   1875   // Return the generated code.
   1876   return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
   1877 }
   1878 
   1879 
   1880 #undef __
   1881 
   1882 
   1883 void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
   1884   Handle<Code> code(masm->isolate()->builtins()->builtin(name));
   1885   GenerateTailCall(masm, code);
   1886 }
   1887 
   1888 
   1889 void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
   1890   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
   1891 }
   1892 
   1893 
   1894 void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
   1895   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
   1896 }
   1897 
   1898 
   1899 void StoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
   1900   GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
   1901 }
   1902 
   1903 
   1904 void KeyedStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
   1905   GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
   1906 }
   1907 
   1908 
   1909 Handle<Code> BaseLoadStoreStubCompiler::GetICCode(Code::Kind kind,
   1910                                                   Code::StubType type,
   1911                                                   Handle<Name> name,
   1912                                                   InlineCacheState state) {
   1913   Code::Flags flags = Code::ComputeFlags(
   1914       kind, state, extra_state(), type);
   1915   Handle<Code> code = GetCodeWithFlags(flags, name);
   1916   PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
   1917   JitEvent(name, code);
   1918   return code;
   1919 }
   1920 
   1921 
   1922 Handle<Code> BaseLoadStubCompiler::GetCode(Code::Kind kind,
   1923                                            Code::StubType type,
   1924                                            Handle<Name> name) {
   1925   ASSERT(type != Code::NORMAL);
   1926   Code::Flags flags = Code::ComputeFlags(
   1927       Code::STUB, MONOMORPHIC, Code::kNoExtraICState, type, kind);
   1928   Handle<Code> code = GetCodeWithFlags(flags, name);
   1929   PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
   1930   JitEvent(name, code);
   1931   return code;
   1932 }
   1933 
   1934 
   1935 Handle<Code> BaseStoreStubCompiler::GetCode(Code::Kind kind,
   1936                                             Code::StubType type,
   1937                                             Handle<Name> name) {
   1938   ASSERT(type != Code::NORMAL);
   1939   Code::Flags flags = Code::ComputeFlags(
   1940       Code::STUB, MONOMORPHIC, extra_state(), type, kind);
   1941   Handle<Code> code = GetCodeWithFlags(flags, name);
   1942   PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
   1943   JitEvent(name, code);
   1944   return code;
   1945 }
   1946 
   1947 
   1948 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
   1949                                                    CodeHandleList* handlers) {
   1950   for (int i = 0; i < receiver_maps->length(); ++i) {
   1951     Handle<Map> receiver_map = receiver_maps->at(i);
   1952     Handle<Code> cached_stub;
   1953 
   1954     if ((receiver_map->instance_type() & kNotStringTag) == 0) {
   1955       cached_stub = isolate()->builtins()->KeyedLoadIC_String();
   1956     } else {
   1957       bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   1958       ElementsKind elements_kind = receiver_map->elements_kind();
   1959 
   1960       if (IsFastElementsKind(elements_kind) ||
   1961           IsExternalArrayElementsKind(elements_kind)) {
   1962         cached_stub =
   1963             KeyedLoadFastElementStub(is_js_array,
   1964                                      elements_kind).GetCode(isolate());
   1965       } else {
   1966         ASSERT(elements_kind == DICTIONARY_ELEMENTS);
   1967         cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate());
   1968       }
   1969     }
   1970 
   1971     handlers->Add(cached_stub);
   1972   }
   1973 }
   1974 
   1975 
   1976 Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
   1977     MapHandleList* receiver_maps) {
   1978   // Collect MONOMORPHIC stubs for all |receiver_maps|.
   1979   CodeHandleList handlers(receiver_maps->length());
   1980   MapHandleList transitioned_maps(receiver_maps->length());
   1981   for (int i = 0; i < receiver_maps->length(); ++i) {
   1982     Handle<Map> receiver_map(receiver_maps->at(i));
   1983     Handle<Code> cached_stub;
   1984     Handle<Map> transitioned_map =
   1985         receiver_map->FindTransitionedMap(receiver_maps);
   1986 
   1987     // TODO(mvstanton): The code below is doing pessimistic elements
   1988     // transitions. I would like to stop doing that and rely on Allocation Site
   1989     // Tracking to do a better job of ensuring the data types are what they need
   1990     // to be. Not all the elements are in place yet, pessimistic elements
   1991     // transitions are still important for performance.
   1992     bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   1993     ElementsKind elements_kind = receiver_map->elements_kind();
   1994     if (!transitioned_map.is_null()) {
   1995       cached_stub = ElementsTransitionAndStoreStub(
   1996           elements_kind,
   1997           transitioned_map->elements_kind(),
   1998           is_js_array,
   1999           store_mode_).GetCode(isolate());
   2000     } else {
   2001       if (FLAG_compiled_keyed_stores &&
   2002           (receiver_map->has_fast_elements() ||
   2003            receiver_map->has_external_array_elements())) {
   2004         cached_stub = KeyedStoreFastElementStub(
   2005             is_js_array,
   2006             elements_kind,
   2007             store_mode_).GetCode(isolate());
   2008       } else {
   2009         cached_stub = KeyedStoreElementStub(
   2010             is_js_array,
   2011             elements_kind,
   2012             store_mode_).GetCode(isolate());
   2013       }
   2014     }
   2015     ASSERT(!cached_stub.is_null());
   2016     handlers.Add(cached_stub);
   2017     transitioned_maps.Add(transitioned_map);
   2018   }
   2019   Handle<Code> code =
   2020       CompileStorePolymorphic(receiver_maps, &handlers, &transitioned_maps);
   2021   isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
   2022   PROFILE(isolate(),
   2023           CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0));
   2024   return code;
   2025 }
   2026 
   2027 
   2028 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
   2029     MacroAssembler* masm) {
   2030   KeyedStoreIC::GenerateSlow(masm);
   2031 }
   2032 
   2033 
   2034 CallStubCompiler::CallStubCompiler(Isolate* isolate,
   2035                                    int argc,
   2036                                    Code::Kind kind,
   2037                                    Code::ExtraICState extra_state,
   2038                                    InlineCacheHolderFlag cache_holder)
   2039     : StubCompiler(isolate),
   2040       arguments_(argc),
   2041       kind_(kind),
   2042       extra_state_(extra_state),
   2043       cache_holder_(cache_holder) {
   2044 }
   2045 
   2046 
   2047 bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
   2048   if (function->shared()->HasBuiltinFunctionId()) {
   2049     BuiltinFunctionId id = function->shared()->builtin_function_id();
   2050 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
   2051     CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
   2052 #undef CALL_GENERATOR_CASE
   2053   }
   2054 
   2055   CallOptimization optimization(function);
   2056   return optimization.is_simple_api_call();
   2057 }
   2058 
   2059 
   2060 bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) {
   2061   if (function->shared()->HasBuiltinFunctionId()) {
   2062     BuiltinFunctionId id = function->shared()->builtin_function_id();
   2063 #define CALL_GENERATOR_CASE(name) if (id == k##name) return false;
   2064     SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE)
   2065 #undef CALL_GENERATOR_CASE
   2066   }
   2067 
   2068   return true;
   2069 }
   2070 
   2071 
   2072 Handle<Code> CallStubCompiler::CompileCustomCall(
   2073     Handle<Object> object,
   2074     Handle<JSObject> holder,
   2075     Handle<Cell> cell,
   2076     Handle<JSFunction> function,
   2077     Handle<String> fname,
   2078     Code::StubType type) {
   2079   ASSERT(HasCustomCallGenerator(function));
   2080 
   2081   if (function->shared()->HasBuiltinFunctionId()) {
   2082     BuiltinFunctionId id = function->shared()->builtin_function_id();
   2083 #define CALL_GENERATOR_CASE(name)                               \
   2084     if (id == k##name) {                                        \
   2085       return CallStubCompiler::Compile##name##Call(object,      \
   2086                                                    holder,      \
   2087                                                    cell,        \
   2088                                                    function,    \
   2089                                                    fname,       \
   2090                                                    type);       \
   2091     }
   2092     CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
   2093 #undef CALL_GENERATOR_CASE
   2094   }
   2095   CallOptimization optimization(function);
   2096   ASSERT(optimization.is_simple_api_call());
   2097   return CompileFastApiCall(optimization,
   2098                             object,
   2099                             holder,
   2100                             cell,
   2101                             function,
   2102                             fname);
   2103 }
   2104 
   2105 
   2106 Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
   2107                                        Handle<Name> name) {
   2108   int argc = arguments_.immediate();
   2109   Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
   2110                                                     extra_state_,
   2111                                                     type,
   2112                                                     argc,
   2113                                                     cache_holder_);
   2114   return GetCodeWithFlags(flags, name);
   2115 }
   2116 
   2117 
   2118 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
   2119   Handle<String> function_name;
   2120   if (function->shared()->name()->IsString()) {
   2121     function_name = Handle<String>(String::cast(function->shared()->name()));
   2122   }
   2123   return GetCode(Code::CONSTANT, function_name);
   2124 }
   2125 
   2126 
   2127 CallOptimization::CallOptimization(LookupResult* lookup) {
   2128   if (lookup->IsFound() &&
   2129       lookup->IsCacheable() &&
   2130       lookup->IsConstantFunction()) {
   2131     // We only optimize constant function calls.
   2132     Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
   2133   } else {
   2134     Initialize(Handle<JSFunction>::null());
   2135   }
   2136 }
   2137 
   2138 
   2139 CallOptimization::CallOptimization(Handle<JSFunction> function) {
   2140   Initialize(function);
   2141 }
   2142 
   2143 
   2144 int CallOptimization::GetPrototypeDepthOfExpectedType(
   2145     Handle<JSObject> object,
   2146     Handle<JSObject> holder) const {
   2147   ASSERT(is_simple_api_call());
   2148   if (expected_receiver_type_.is_null()) return 0;
   2149   int depth = 0;
   2150   while (!object.is_identical_to(holder)) {
   2151     if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
   2152     object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
   2153     if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth;
   2154     ++depth;
   2155   }
   2156   if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
   2157   return kInvalidProtoDepth;
   2158 }
   2159 
   2160 
   2161 void CallOptimization::Initialize(Handle<JSFunction> function) {
   2162   constant_function_ = Handle<JSFunction>::null();
   2163   is_simple_api_call_ = false;
   2164   expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
   2165   api_call_info_ = Handle<CallHandlerInfo>::null();
   2166 
   2167   if (function.is_null() || !function->is_compiled()) return;
   2168 
   2169   constant_function_ = function;
   2170   AnalyzePossibleApiFunction(function);
   2171 }
   2172 
   2173 
   2174 void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
   2175   if (!function->shared()->IsApiFunction()) return;
   2176   Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
   2177 
   2178   // Require a C++ callback.
   2179   if (info->call_code()->IsUndefined()) return;
   2180   api_call_info_ =
   2181       Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
   2182 
   2183   // Accept signatures that either have no restrictions at all or
   2184   // only have restrictions on the receiver.
   2185   if (!info->signature()->IsUndefined()) {
   2186     Handle<SignatureInfo> signature =
   2187         Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
   2188     if (!signature->args()->IsUndefined()) return;
   2189     if (!signature->receiver()->IsUndefined()) {
   2190       expected_receiver_type_ =
   2191           Handle<FunctionTemplateInfo>(
   2192               FunctionTemplateInfo::cast(signature->receiver()));
   2193     }
   2194   }
   2195 
   2196   is_simple_api_call_ = true;
   2197 }
   2198 
   2199 
   2200 } }  // namespace v8::internal
   2201