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