Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2009 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 "ic-inl.h"
     33 #include "stub-cache.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 // -----------------------------------------------------------------------
     39 // StubCache implementation.
     40 
     41 
     42 StubCache::Entry StubCache::primary_[StubCache::kPrimaryTableSize];
     43 StubCache::Entry StubCache::secondary_[StubCache::kSecondaryTableSize];
     44 
     45 void StubCache::Initialize(bool create_heap_objects) {
     46   ASSERT(IsPowerOf2(kPrimaryTableSize));
     47   ASSERT(IsPowerOf2(kSecondaryTableSize));
     48   if (create_heap_objects) {
     49     HandleScope scope;
     50     Clear();
     51   }
     52 }
     53 
     54 
     55 Code* StubCache::Set(String* name, Map* map, Code* code) {
     56   // Get the flags from the code.
     57   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
     58 
     59   // Validate that the name does not move on scavenge, and that we
     60   // can use identity checks instead of string equality checks.
     61   ASSERT(!Heap::InNewSpace(name));
     62   ASSERT(name->IsSymbol());
     63 
     64   // The state bits are not important to the hash function because
     65   // the stub cache only contains monomorphic stubs. Make sure that
     66   // the bits are the least significant so they will be the ones
     67   // masked out.
     68   ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
     69   ASSERT(Code::kFlagsICStateShift == 0);
     70 
     71   // Make sure that the code type is not included in the hash.
     72   ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
     73 
     74   // Compute the primary entry.
     75   int primary_offset = PrimaryOffset(name, flags, map);
     76   Entry* primary = entry(primary_, primary_offset);
     77   Code* hit = primary->value;
     78 
     79   // If the primary entry has useful data in it, we retire it to the
     80   // secondary cache before overwriting it.
     81   if (hit != Builtins::builtin(Builtins::Illegal)) {
     82     Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
     83     int secondary_offset =
     84         SecondaryOffset(primary->key, primary_flags, primary_offset);
     85     Entry* secondary = entry(secondary_, secondary_offset);
     86     *secondary = *primary;
     87   }
     88 
     89   // Update primary cache.
     90   primary->key = name;
     91   primary->value = code;
     92   return code;
     93 }
     94 
     95 
     96 Object* StubCache::ComputeLoadField(String* name,
     97                                     JSObject* receiver,
     98                                     JSObject* holder,
     99                                     int field_index) {
    100   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
    101   Object* code = receiver->map()->FindInCodeCache(name, flags);
    102   if (code->IsUndefined()) {
    103     LoadStubCompiler compiler;
    104     code = compiler.CompileLoadField(receiver, holder, field_index, name);
    105     if (code->IsFailure()) return code;
    106     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
    107     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    108     if (result->IsFailure()) return result;
    109   }
    110   return Set(name, receiver->map(), Code::cast(code));
    111 }
    112 
    113 
    114 Object* StubCache::ComputeLoadCallback(String* name,
    115                                        JSObject* receiver,
    116                                        JSObject* holder,
    117                                        AccessorInfo* callback) {
    118   ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
    119   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
    120   Object* code = receiver->map()->FindInCodeCache(name, flags);
    121   if (code->IsUndefined()) {
    122     LoadStubCompiler compiler;
    123     code = compiler.CompileLoadCallback(name, receiver, holder, callback);
    124     if (code->IsFailure()) return code;
    125     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
    126     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    127     if (result->IsFailure()) return result;
    128   }
    129   return Set(name, receiver->map(), Code::cast(code));
    130 }
    131 
    132 
    133 Object* StubCache::ComputeLoadConstant(String* name,
    134                                        JSObject* receiver,
    135                                        JSObject* holder,
    136                                        Object* value) {
    137   Code::Flags flags =
    138       Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
    139   Object* code = receiver->map()->FindInCodeCache(name, flags);
    140   if (code->IsUndefined()) {
    141     LoadStubCompiler compiler;
    142     code = compiler.CompileLoadConstant(receiver, holder, value, name);
    143     if (code->IsFailure()) return code;
    144     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
    145     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    146     if (result->IsFailure()) return result;
    147   }
    148   return Set(name, receiver->map(), Code::cast(code));
    149 }
    150 
    151 
    152 Object* StubCache::ComputeLoadInterceptor(String* name,
    153                                           JSObject* receiver,
    154                                           JSObject* holder) {
    155   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
    156   Object* code = receiver->map()->FindInCodeCache(name, flags);
    157   if (code->IsUndefined()) {
    158     LoadStubCompiler compiler;
    159     code = compiler.CompileLoadInterceptor(receiver, holder, name);
    160     if (code->IsFailure()) return code;
    161     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
    162     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    163     if (result->IsFailure()) return result;
    164   }
    165   return Set(name, receiver->map(), Code::cast(code));
    166 }
    167 
    168 
    169 Object* StubCache::ComputeLoadNormal(String* name, JSObject* receiver) {
    170   Code* code = Builtins::builtin(Builtins::LoadIC_Normal);
    171   return Set(name, receiver->map(), code);
    172 }
    173 
    174 
    175 Object* StubCache::ComputeLoadGlobal(String* name,
    176                                      JSObject* receiver,
    177                                      GlobalObject* holder,
    178                                      JSGlobalPropertyCell* cell,
    179                                      bool is_dont_delete) {
    180   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
    181   Object* code = receiver->map()->FindInCodeCache(name, flags);
    182   if (code->IsUndefined()) {
    183     LoadStubCompiler compiler;
    184     code = compiler.CompileLoadGlobal(receiver,
    185                                       holder,
    186                                       cell,
    187                                       name,
    188                                       is_dont_delete);
    189     if (code->IsFailure()) return code;
    190     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
    191     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    192     if (result->IsFailure()) return result;
    193   }
    194   return Set(name, receiver->map(), Code::cast(code));
    195 }
    196 
    197 
    198 Object* StubCache::ComputeKeyedLoadField(String* name,
    199                                          JSObject* receiver,
    200                                          JSObject* holder,
    201                                          int field_index) {
    202   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
    203   Object* code = receiver->map()->FindInCodeCache(name, flags);
    204   if (code->IsUndefined()) {
    205     KeyedLoadStubCompiler compiler;
    206     code = compiler.CompileLoadField(name, receiver, holder, field_index);
    207     if (code->IsFailure()) return code;
    208     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    209     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    210     if (result->IsFailure()) return result;
    211   }
    212   return code;
    213 }
    214 
    215 
    216 Object* StubCache::ComputeKeyedLoadConstant(String* name,
    217                                             JSObject* receiver,
    218                                             JSObject* holder,
    219                                             Object* value) {
    220   Code::Flags flags =
    221       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
    222   Object* code = receiver->map()->FindInCodeCache(name, flags);
    223   if (code->IsUndefined()) {
    224     KeyedLoadStubCompiler compiler;
    225     code = compiler.CompileLoadConstant(name, receiver, holder, value);
    226     if (code->IsFailure()) return code;
    227     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    228     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    229     if (result->IsFailure()) return result;
    230   }
    231   return code;
    232 }
    233 
    234 
    235 Object* StubCache::ComputeKeyedLoadInterceptor(String* name,
    236                                                JSObject* receiver,
    237                                                JSObject* holder) {
    238   Code::Flags flags =
    239       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
    240   Object* code = receiver->map()->FindInCodeCache(name, flags);
    241   if (code->IsUndefined()) {
    242     KeyedLoadStubCompiler compiler;
    243     code = compiler.CompileLoadInterceptor(receiver, holder, name);
    244     if (code->IsFailure()) return code;
    245     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    246     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    247     if (result->IsFailure()) return result;
    248   }
    249   return code;
    250 }
    251 
    252 
    253 Object* StubCache::ComputeKeyedLoadCallback(String* name,
    254                                             JSObject* receiver,
    255                                             JSObject* holder,
    256                                             AccessorInfo* callback) {
    257   Code::Flags flags =
    258       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
    259   Object* code = receiver->map()->FindInCodeCache(name, flags);
    260   if (code->IsUndefined()) {
    261     KeyedLoadStubCompiler compiler;
    262     code = compiler.CompileLoadCallback(name, receiver, holder, callback);
    263     if (code->IsFailure()) return code;
    264     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    265     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    266     if (result->IsFailure()) return result;
    267   }
    268   return code;
    269 }
    270 
    271 
    272 
    273 Object* StubCache::ComputeKeyedLoadArrayLength(String* name,
    274                                                JSArray* receiver) {
    275   Code::Flags flags =
    276       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
    277   Object* code = receiver->map()->FindInCodeCache(name, flags);
    278   if (code->IsUndefined()) {
    279     KeyedLoadStubCompiler compiler;
    280     code = compiler.CompileLoadArrayLength(name);
    281     if (code->IsFailure()) return code;
    282     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    283     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    284     if (result->IsFailure()) return result;
    285   }
    286   return code;
    287 }
    288 
    289 
    290 Object* StubCache::ComputeKeyedLoadStringLength(String* name,
    291                                                 String* receiver) {
    292   Code::Flags flags =
    293       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
    294   Object* code = receiver->map()->FindInCodeCache(name, flags);
    295   if (code->IsUndefined()) {
    296     KeyedLoadStubCompiler compiler;
    297     code = compiler.CompileLoadStringLength(name);
    298     if (code->IsFailure()) return code;
    299     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    300     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    301     if (result->IsFailure()) return result;
    302   }
    303   return code;
    304 }
    305 
    306 
    307 Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name,
    308                                                      JSFunction* receiver) {
    309   Code::Flags flags =
    310       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
    311   Object* code = receiver->map()->FindInCodeCache(name, flags);
    312   if (code->IsUndefined()) {
    313     KeyedLoadStubCompiler compiler;
    314     code = compiler.CompileLoadFunctionPrototype(name);
    315     if (code->IsFailure()) return code;
    316     LOG(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
    317     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    318     if (result->IsFailure()) return result;
    319   }
    320   return code;
    321 }
    322 
    323 
    324 Object* StubCache::ComputeStoreField(String* name,
    325                                      JSObject* receiver,
    326                                      int field_index,
    327                                      Map* transition) {
    328   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
    329   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
    330   Object* code = receiver->map()->FindInCodeCache(name, flags);
    331   if (code->IsUndefined()) {
    332     StoreStubCompiler compiler;
    333     code = compiler.CompileStoreField(receiver, field_index, transition, name);
    334     if (code->IsFailure()) return code;
    335     LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
    336     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    337     if (result->IsFailure()) return result;
    338   }
    339   return Set(name, receiver->map(), Code::cast(code));
    340 }
    341 
    342 
    343 Object* StubCache::ComputeStoreGlobal(String* name,
    344                                       GlobalObject* receiver,
    345                                       JSGlobalPropertyCell* cell) {
    346   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
    347   Object* code = receiver->map()->FindInCodeCache(name, flags);
    348   if (code->IsUndefined()) {
    349     StoreStubCompiler compiler;
    350     code = compiler.CompileStoreGlobal(receiver, cell, name);
    351     if (code->IsFailure()) return code;
    352     LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
    353     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    354     if (result->IsFailure()) return result;
    355   }
    356   return Set(name, receiver->map(), Code::cast(code));
    357 }
    358 
    359 
    360 Object* StubCache::ComputeStoreCallback(String* name,
    361                                         JSObject* receiver,
    362                                         AccessorInfo* callback) {
    363   ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
    364   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, CALLBACKS);
    365   Object* code = receiver->map()->FindInCodeCache(name, flags);
    366   if (code->IsUndefined()) {
    367     StoreStubCompiler compiler;
    368     code = compiler.CompileStoreCallback(receiver, callback, name);
    369     if (code->IsFailure()) return code;
    370     LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
    371     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    372     if (result->IsFailure()) return result;
    373   }
    374   return Set(name, receiver->map(), Code::cast(code));
    375 }
    376 
    377 
    378 Object* StubCache::ComputeStoreInterceptor(String* name,
    379                                            JSObject* receiver) {
    380   Code::Flags flags =
    381       Code::ComputeMonomorphicFlags(Code::STORE_IC, INTERCEPTOR);
    382   Object* code = receiver->map()->FindInCodeCache(name, flags);
    383   if (code->IsUndefined()) {
    384     StoreStubCompiler compiler;
    385     code = compiler.CompileStoreInterceptor(receiver, name);
    386     if (code->IsFailure()) return code;
    387     LOG(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
    388     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    389     if (result->IsFailure()) return result;
    390   }
    391   return Set(name, receiver->map(), Code::cast(code));
    392 }
    393 
    394 
    395 Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver,
    396                                           int field_index, Map* transition) {
    397   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
    398   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
    399   Object* code = receiver->map()->FindInCodeCache(name, flags);
    400   if (code->IsUndefined()) {
    401     KeyedStoreStubCompiler compiler;
    402     code = compiler.CompileStoreField(receiver, field_index, transition, name);
    403     if (code->IsFailure()) return code;
    404     LOG(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), name));
    405     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    406     if (result->IsFailure()) return result;
    407   }
    408   return code;
    409 }
    410 
    411 
    412 Object* StubCache::ComputeCallConstant(int argc,
    413                                        InLoopFlag in_loop,
    414                                        String* name,
    415                                        Object* object,
    416                                        JSObject* holder,
    417                                        JSFunction* function) {
    418   // Compute the check type and the map.
    419   Map* map = IC::GetCodeCacheMapForObject(object);
    420 
    421   // Compute check type based on receiver/holder.
    422   StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK;
    423   if (object->IsString()) {
    424     check = StubCompiler::STRING_CHECK;
    425   } else if (object->IsNumber()) {
    426     check = StubCompiler::NUMBER_CHECK;
    427   } else if (object->IsBoolean()) {
    428     check = StubCompiler::BOOLEAN_CHECK;
    429   }
    430 
    431   Code::Flags flags =
    432       Code::ComputeMonomorphicFlags(Code::CALL_IC,
    433                                     CONSTANT_FUNCTION,
    434                                     in_loop,
    435                                     argc);
    436   Object* code = map->FindInCodeCache(name, flags);
    437   if (code->IsUndefined()) {
    438     if (object->IsJSObject()) {
    439       Object* opt =
    440           Top::LookupSpecialFunction(JSObject::cast(object), holder, function);
    441       if (opt->IsJSFunction()) {
    442         check = StubCompiler::JSARRAY_HAS_FAST_ELEMENTS_CHECK;
    443         function = JSFunction::cast(opt);
    444       }
    445     }
    446     // If the function hasn't been compiled yet, we cannot do it now
    447     // because it may cause GC. To avoid this issue, we return an
    448     // internal error which will make sure we do not update any
    449     // caches.
    450     if (!function->is_compiled()) return Failure::InternalError();
    451     // Compile the stub - only create stubs for fully compiled functions.
    452     CallStubCompiler compiler(argc, in_loop);
    453     code = compiler.CompileCallConstant(object, holder, function, name, check);
    454     if (code->IsFailure()) return code;
    455     ASSERT_EQ(flags, Code::cast(code)->flags());
    456     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
    457     Object* result = map->UpdateCodeCache(name, Code::cast(code));
    458     if (result->IsFailure()) return result;
    459   }
    460   return Set(name, map, Code::cast(code));
    461 }
    462 
    463 
    464 Object* StubCache::ComputeCallField(int argc,
    465                                     InLoopFlag in_loop,
    466                                     String* name,
    467                                     Object* object,
    468                                     JSObject* holder,
    469                                     int index) {
    470   // Compute the check type and the map.
    471   Map* map = IC::GetCodeCacheMapForObject(object);
    472 
    473   // TODO(1233596): We cannot do receiver map check for non-JS objects
    474   // because they may be represented as immediates without a
    475   // map. Instead, we check against the map in the holder.
    476   if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
    477     object = holder;
    478   }
    479 
    480   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
    481                                                     FIELD,
    482                                                     in_loop,
    483                                                     argc);
    484   Object* code = map->FindInCodeCache(name, flags);
    485   if (code->IsUndefined()) {
    486     CallStubCompiler compiler(argc, in_loop);
    487     code = compiler.CompileCallField(JSObject::cast(object),
    488                                      holder,
    489                                      index,
    490                                      name);
    491     if (code->IsFailure()) return code;
    492     ASSERT_EQ(flags, Code::cast(code)->flags());
    493     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
    494     Object* result = map->UpdateCodeCache(name, Code::cast(code));
    495     if (result->IsFailure()) return result;
    496   }
    497   return Set(name, map, Code::cast(code));
    498 }
    499 
    500 
    501 Object* StubCache::ComputeCallInterceptor(int argc,
    502                                           String* name,
    503                                           Object* object,
    504                                           JSObject* holder) {
    505   // Compute the check type and the map.
    506   // If the object is a value, we use the prototype map for the cache.
    507   Map* map = IC::GetCodeCacheMapForObject(object);
    508 
    509   // TODO(1233596): We cannot do receiver map check for non-JS objects
    510   // because they may be represented as immediates without a
    511   // map. Instead, we check against the map in the holder.
    512   if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
    513     object = holder;
    514   }
    515 
    516   Code::Flags flags =
    517       Code::ComputeMonomorphicFlags(Code::CALL_IC,
    518                                     INTERCEPTOR,
    519                                     NOT_IN_LOOP,
    520                                     argc);
    521   Object* code = map->FindInCodeCache(name, flags);
    522   if (code->IsUndefined()) {
    523     CallStubCompiler compiler(argc, NOT_IN_LOOP);
    524     code = compiler.CompileCallInterceptor(JSObject::cast(object),
    525                                            holder,
    526                                            name);
    527     if (code->IsFailure()) return code;
    528     ASSERT_EQ(flags, Code::cast(code)->flags());
    529     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
    530     Object* result = map->UpdateCodeCache(name, Code::cast(code));
    531     if (result->IsFailure()) return result;
    532   }
    533   return Set(name, map, Code::cast(code));
    534 }
    535 
    536 
    537 Object* StubCache::ComputeCallNormal(int argc,
    538                                      InLoopFlag in_loop,
    539                                      String* name,
    540                                      JSObject* receiver) {
    541   Object* code = ComputeCallNormal(argc, in_loop);
    542   if (code->IsFailure()) return code;
    543   return Set(name, receiver->map(), Code::cast(code));
    544 }
    545 
    546 
    547 Object* StubCache::ComputeCallGlobal(int argc,
    548                                      InLoopFlag in_loop,
    549                                      String* name,
    550                                      JSObject* receiver,
    551                                      GlobalObject* holder,
    552                                      JSGlobalPropertyCell* cell,
    553                                      JSFunction* function) {
    554   Code::Flags flags =
    555       Code::ComputeMonomorphicFlags(Code::CALL_IC, NORMAL, in_loop, argc);
    556   Object* code = receiver->map()->FindInCodeCache(name, flags);
    557   if (code->IsUndefined()) {
    558     // If the function hasn't been compiled yet, we cannot do it now
    559     // because it may cause GC. To avoid this issue, we return an
    560     // internal error which will make sure we do not update any
    561     // caches.
    562     if (!function->is_compiled()) return Failure::InternalError();
    563     CallStubCompiler compiler(argc, in_loop);
    564     code = compiler.CompileCallGlobal(receiver, holder, cell, function, name);
    565     if (code->IsFailure()) return code;
    566     ASSERT_EQ(flags, Code::cast(code)->flags());
    567     LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
    568     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
    569     if (result->IsFailure()) return result;
    570   }
    571   return Set(name, receiver->map(), Code::cast(code));
    572 }
    573 
    574 
    575 static Object* GetProbeValue(Code::Flags flags) {
    576   // Use raw_unchecked... so we don't get assert failures during GC.
    577   NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache();
    578   int entry = dictionary->FindEntry(flags);
    579   if (entry != -1) return dictionary->ValueAt(entry);
    580   return Heap::raw_unchecked_undefined_value();
    581 }
    582 
    583 
    584 static Object* ProbeCache(Code::Flags flags) {
    585   Object* probe = GetProbeValue(flags);
    586   if (probe != Heap::undefined_value()) return probe;
    587   // Seed the cache with an undefined value to make sure that any
    588   // generated code object can always be inserted into the cache
    589   // without causing  allocation failures.
    590   Object* result =
    591       Heap::non_monomorphic_cache()->AtNumberPut(flags,
    592                                                  Heap::undefined_value());
    593   if (result->IsFailure()) return result;
    594   Heap::public_set_non_monomorphic_cache(NumberDictionary::cast(result));
    595   return probe;
    596 }
    597 
    598 
    599 static Object* FillCache(Object* code) {
    600   if (code->IsCode()) {
    601     int entry =
    602         Heap::non_monomorphic_cache()->FindEntry(
    603             Code::cast(code)->flags());
    604     // The entry must be present see comment in ProbeCache.
    605     ASSERT(entry != -1);
    606     ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) ==
    607            Heap::undefined_value());
    608     Heap::non_monomorphic_cache()->ValueAtPut(entry, code);
    609     CHECK(GetProbeValue(Code::cast(code)->flags()) == code);
    610   }
    611   return code;
    612 }
    613 
    614 
    615 Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) {
    616   Code::Flags flags =
    617       Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc);
    618   Object* result = ProbeCache(flags);
    619   ASSERT(!result->IsUndefined());
    620   // This might be called during the marking phase of the collector
    621   // hence the unchecked cast.
    622   return reinterpret_cast<Code*>(result);
    623 }
    624 
    625 
    626 Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
    627   Code::Flags flags =
    628       Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL, argc);
    629   Object* probe = ProbeCache(flags);
    630   if (!probe->IsUndefined()) return probe;
    631   StubCompiler compiler;
    632   return FillCache(compiler.CompileCallInitialize(flags));
    633 }
    634 
    635 
    636 Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop) {
    637   Code::Flags flags =
    638       Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL, argc);
    639   Object* probe = ProbeCache(flags);
    640   if (!probe->IsUndefined()) return probe;
    641   StubCompiler compiler;
    642   return FillCache(compiler.CompileCallPreMonomorphic(flags));
    643 }
    644 
    645 
    646 Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) {
    647   Code::Flags flags =
    648       Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL, argc);
    649   Object* probe = ProbeCache(flags);
    650   if (!probe->IsUndefined()) return probe;
    651   StubCompiler compiler;
    652   return FillCache(compiler.CompileCallNormal(flags));
    653 }
    654 
    655 
    656 Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) {
    657   Code::Flags flags =
    658       Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL, argc);
    659   Object* probe = ProbeCache(flags);
    660   if (!probe->IsUndefined()) return probe;
    661   StubCompiler compiler;
    662   return FillCache(compiler.CompileCallMegamorphic(flags));
    663 }
    664 
    665 
    666 Object* StubCache::ComputeCallMiss(int argc) {
    667   Code::Flags flags =
    668       Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL, argc);
    669   Object* probe = ProbeCache(flags);
    670   if (!probe->IsUndefined()) return probe;
    671   StubCompiler compiler;
    672   return FillCache(compiler.CompileCallMiss(flags));
    673 }
    674 
    675 
    676 #ifdef ENABLE_DEBUGGER_SUPPORT
    677 Object* StubCache::ComputeCallDebugBreak(int argc) {
    678   Code::Flags flags =
    679       Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc);
    680   Object* probe = ProbeCache(flags);
    681   if (!probe->IsUndefined()) return probe;
    682   StubCompiler compiler;
    683   return FillCache(compiler.CompileCallDebugBreak(flags));
    684 }
    685 
    686 
    687 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
    688   Code::Flags flags =
    689       Code::ComputeFlags(Code::CALL_IC,
    690                          NOT_IN_LOOP,
    691                          DEBUG_PREPARE_STEP_IN,
    692                          NORMAL,
    693                          argc);
    694   Object* probe = ProbeCache(flags);
    695   if (!probe->IsUndefined()) return probe;
    696   StubCompiler compiler;
    697   return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
    698 }
    699 #endif
    700 
    701 
    702 Object* StubCache::ComputeLazyCompile(int argc) {
    703   Code::Flags flags =
    704       Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, UNINITIALIZED, NORMAL, argc);
    705   Object* probe = ProbeCache(flags);
    706   if (!probe->IsUndefined()) return probe;
    707   StubCompiler compiler;
    708   Object* result = FillCache(compiler.CompileLazyCompile(flags));
    709   if (result->IsCode()) {
    710     Code* code = Code::cast(result);
    711     USE(code);
    712     LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG,
    713                         code, code->arguments_count()));
    714   }
    715   return result;
    716 }
    717 
    718 
    719 void StubCache::Clear() {
    720   for (int i = 0; i < kPrimaryTableSize; i++) {
    721     primary_[i].key = Heap::empty_string();
    722     primary_[i].value = Builtins::builtin(Builtins::Illegal);
    723   }
    724   for (int j = 0; j < kSecondaryTableSize; j++) {
    725     secondary_[j].key = Heap::empty_string();
    726     secondary_[j].value = Builtins::builtin(Builtins::Illegal);
    727   }
    728 }
    729 
    730 
    731 // ------------------------------------------------------------------------
    732 // StubCompiler implementation.
    733 
    734 
    735 // Support function for computing call IC miss stubs.
    736 Handle<Code> ComputeCallMiss(int argc) {
    737   CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code);
    738 }
    739 
    740 
    741 
    742 Object* LoadCallbackProperty(Arguments args) {
    743   ASSERT(args[0]->IsJSObject());
    744   ASSERT(args[1]->IsJSObject());
    745   AccessorInfo* callback = AccessorInfo::cast(args[2]);
    746   Address getter_address = v8::ToCData<Address>(callback->getter());
    747   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
    748   ASSERT(fun != NULL);
    749   CustomArguments custom_args(callback->data(),
    750                               JSObject::cast(args[0]),
    751                               JSObject::cast(args[1]));
    752   v8::AccessorInfo info(custom_args.end());
    753   HandleScope scope;
    754   v8::Handle<v8::Value> result;
    755   {
    756     // Leaving JavaScript.
    757     VMState state(EXTERNAL);
    758 #ifdef ENABLE_LOGGING_AND_PROFILING
    759     state.set_external_callback(getter_address);
    760 #endif
    761     result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
    762   }
    763   RETURN_IF_SCHEDULED_EXCEPTION();
    764   if (result.IsEmpty()) return Heap::undefined_value();
    765   return *v8::Utils::OpenHandle(*result);
    766 }
    767 
    768 
    769 Object* StoreCallbackProperty(Arguments args) {
    770   JSObject* recv = JSObject::cast(args[0]);
    771   AccessorInfo* callback = AccessorInfo::cast(args[1]);
    772   Address setter_address = v8::ToCData<Address>(callback->setter());
    773   v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
    774   ASSERT(fun != NULL);
    775   Handle<String> name = args.at<String>(2);
    776   Handle<Object> value = args.at<Object>(3);
    777   HandleScope scope;
    778   LOG(ApiNamedPropertyAccess("store", recv, *name));
    779   CustomArguments custom_args(callback->data(), recv, recv);
    780   v8::AccessorInfo info(custom_args.end());
    781   {
    782     // Leaving JavaScript.
    783     VMState state(EXTERNAL);
    784 #ifdef ENABLE_LOGGING_AND_PROFILING
    785     state.set_external_callback(setter_address);
    786 #endif
    787     fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
    788   }
    789   RETURN_IF_SCHEDULED_EXCEPTION();
    790   return *value;
    791 }
    792 
    793 /**
    794  * Attempts to load a property with an interceptor (which must be present),
    795  * but doesn't search the prototype chain.
    796  *
    797  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
    798  * provide any value for the given name.
    799  */
    800 Object* LoadPropertyWithInterceptorOnly(Arguments args) {
    801   JSObject* receiver_handle = JSObject::cast(args[0]);
    802   JSObject* holder_handle = JSObject::cast(args[1]);
    803   Handle<String> name_handle = args.at<String>(2);
    804   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3);
    805   Object* data_handle = args[4];
    806 
    807   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
    808   v8::NamedPropertyGetter getter =
    809       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
    810   ASSERT(getter != NULL);
    811 
    812   {
    813     // Use the interceptor getter.
    814     CustomArguments args(data_handle, receiver_handle, holder_handle);
    815     v8::AccessorInfo info(args.end());
    816     HandleScope scope;
    817     v8::Handle<v8::Value> r;
    818     {
    819       // Leaving JavaScript.
    820       VMState state(EXTERNAL);
    821       r = getter(v8::Utils::ToLocal(name_handle), info);
    822     }
    823     RETURN_IF_SCHEDULED_EXCEPTION();
    824     if (!r.IsEmpty()) {
    825       return *v8::Utils::OpenHandle(*r);
    826     }
    827   }
    828 
    829   return Heap::no_interceptor_result_sentinel();
    830 }
    831 
    832 
    833 static Object* ThrowReferenceError(String* name) {
    834   // If the load is non-contextual, just return the undefined result.
    835   // Note that both keyed and non-keyed loads may end up here, so we
    836   // can't use either LoadIC or KeyedLoadIC constructors.
    837   IC ic(IC::NO_EXTRA_FRAME);
    838   ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
    839   if (!ic.SlowIsContextual()) return Heap::undefined_value();
    840 
    841   // Throw a reference error.
    842   HandleScope scope;
    843   Handle<String> name_handle(name);
    844   Handle<Object> error =
    845       Factory::NewReferenceError("not_defined",
    846                                   HandleVector(&name_handle, 1));
    847   return Top::Throw(*error);
    848 }
    849 
    850 
    851 static Object* LoadWithInterceptor(Arguments* args,
    852                                    PropertyAttributes* attrs) {
    853   Handle<JSObject> receiver_handle = args->at<JSObject>(0);
    854   Handle<JSObject> holder_handle = args->at<JSObject>(1);
    855   Handle<String> name_handle = args->at<String>(2);
    856   Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(3);
    857   Handle<Object> data_handle = args->at<Object>(4);
    858 
    859   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
    860   v8::NamedPropertyGetter getter =
    861       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
    862   ASSERT(getter != NULL);
    863 
    864   {
    865     // Use the interceptor getter.
    866     CustomArguments args(*data_handle, *receiver_handle, *holder_handle);
    867     v8::AccessorInfo info(args.end());
    868     HandleScope scope;
    869     v8::Handle<v8::Value> r;
    870     {
    871       // Leaving JavaScript.
    872       VMState state(EXTERNAL);
    873       r = getter(v8::Utils::ToLocal(name_handle), info);
    874     }
    875     RETURN_IF_SCHEDULED_EXCEPTION();
    876     if (!r.IsEmpty()) {
    877       *attrs = NONE;
    878       return *v8::Utils::OpenHandle(*r);
    879     }
    880   }
    881 
    882   Object* result = holder_handle->GetPropertyPostInterceptor(
    883       *receiver_handle,
    884       *name_handle,
    885       attrs);
    886   RETURN_IF_SCHEDULED_EXCEPTION();
    887   return result;
    888 }
    889 
    890 
    891 /**
    892  * Loads a property with an interceptor performing post interceptor
    893  * lookup if interceptor failed.
    894  */
    895 Object* LoadPropertyWithInterceptorForLoad(Arguments args) {
    896   PropertyAttributes attr = NONE;
    897   Object* result = LoadWithInterceptor(&args, &attr);
    898   if (result->IsFailure()) return result;
    899 
    900   // If the property is present, return it.
    901   if (attr != ABSENT) return result;
    902   return ThrowReferenceError(String::cast(args[2]));
    903 }
    904 
    905 
    906 Object* LoadPropertyWithInterceptorForCall(Arguments args) {
    907   PropertyAttributes attr;
    908   Object* result = LoadWithInterceptor(&args, &attr);
    909   RETURN_IF_SCHEDULED_EXCEPTION();
    910   // This is call IC. In this case, we simply return the undefined result which
    911   // will lead to an exception when trying to invoke the result as a
    912   // function.
    913   return result;
    914 }
    915 
    916 
    917 Object* StoreInterceptorProperty(Arguments args) {
    918   JSObject* recv = JSObject::cast(args[0]);
    919   String* name = String::cast(args[1]);
    920   Object* value = args[2];
    921   ASSERT(recv->HasNamedInterceptor());
    922   PropertyAttributes attr = NONE;
    923   Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
    924   return result;
    925 }
    926 
    927 
    928 Object* KeyedLoadPropertyWithInterceptor(Arguments args) {
    929   JSObject* receiver = JSObject::cast(args[0]);
    930   uint32_t index = Smi::cast(args[1])->value();
    931   return receiver->GetElementWithInterceptor(receiver, index);
    932 }
    933 
    934 
    935 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) {
    936   HandleScope scope;
    937   int argc = Code::ExtractArgumentsCountFromFlags(flags);
    938   CallIC::GenerateInitialize(masm(), argc);
    939   Object* result = GetCodeWithFlags(flags, "CompileCallInitialize");
    940   if (!result->IsFailure()) {
    941     Counters::call_initialize_stubs.Increment();
    942     Code* code = Code::cast(result);
    943     USE(code);
    944     LOG(CodeCreateEvent(Logger::CALL_INITIALIZE_TAG,
    945                         code, code->arguments_count()));
    946   }
    947   return result;
    948 }
    949 
    950 
    951 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
    952   HandleScope scope;
    953   int argc = Code::ExtractArgumentsCountFromFlags(flags);
    954   // The code of the PreMonomorphic stub is the same as the code
    955   // of the Initialized stub.  They just differ on the code object flags.
    956   CallIC::GenerateInitialize(masm(), argc);
    957   Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
    958   if (!result->IsFailure()) {
    959     Counters::call_premonomorphic_stubs.Increment();
    960     Code* code = Code::cast(result);
    961     USE(code);
    962     LOG(CodeCreateEvent(Logger::CALL_PRE_MONOMORPHIC_TAG,
    963                         code, code->arguments_count()));
    964   }
    965   return result;
    966 }
    967 
    968 
    969 Object* StubCompiler::CompileCallNormal(Code::Flags flags) {
    970   HandleScope scope;
    971   int argc = Code::ExtractArgumentsCountFromFlags(flags);
    972   CallIC::GenerateNormal(masm(), argc);
    973   Object* result = GetCodeWithFlags(flags, "CompileCallNormal");
    974   if (!result->IsFailure()) {
    975     Counters::call_normal_stubs.Increment();
    976     Code* code = Code::cast(result);
    977     USE(code);
    978     LOG(CodeCreateEvent(Logger::CALL_NORMAL_TAG,
    979                         code, code->arguments_count()));
    980   }
    981   return result;
    982 }
    983 
    984 
    985 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
    986   HandleScope scope;
    987   int argc = Code::ExtractArgumentsCountFromFlags(flags);
    988   CallIC::GenerateMegamorphic(masm(), argc);
    989   Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic");
    990   if (!result->IsFailure()) {
    991     Counters::call_megamorphic_stubs.Increment();
    992     Code* code = Code::cast(result);
    993     USE(code);
    994     LOG(CodeCreateEvent(Logger::CALL_MEGAMORPHIC_TAG,
    995                         code, code->arguments_count()));
    996   }
    997   return result;
    998 }
    999 
   1000 
   1001 Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
   1002   HandleScope scope;
   1003   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1004   CallIC::GenerateMiss(masm(), argc);
   1005   Object* result = GetCodeWithFlags(flags, "CompileCallMiss");
   1006   if (!result->IsFailure()) {
   1007     Counters::call_megamorphic_stubs.Increment();
   1008     Code* code = Code::cast(result);
   1009     USE(code);
   1010     LOG(CodeCreateEvent(Logger::CALL_MISS_TAG, code, code->arguments_count()));
   1011   }
   1012   return result;
   1013 }
   1014 
   1015 
   1016 #ifdef ENABLE_DEBUGGER_SUPPORT
   1017 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
   1018   HandleScope scope;
   1019   Debug::GenerateCallICDebugBreak(masm());
   1020   Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak");
   1021   if (!result->IsFailure()) {
   1022     Code* code = Code::cast(result);
   1023     USE(code);
   1024     LOG(CodeCreateEvent(Logger::CALL_DEBUG_BREAK_TAG,
   1025                         code, code->arguments_count()));
   1026   }
   1027   return result;
   1028 }
   1029 
   1030 
   1031 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
   1032   HandleScope scope;
   1033   // Use the same code for the the step in preparations as we do for
   1034   // the miss case.
   1035   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   1036   CallIC::GenerateMiss(masm(), argc);
   1037   Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
   1038   if (!result->IsFailure()) {
   1039     Code* code = Code::cast(result);
   1040     USE(code);
   1041     LOG(CodeCreateEvent(Logger::CALL_DEBUG_PREPARE_STEP_IN_TAG,
   1042                         code, code->arguments_count()));
   1043   }
   1044   return result;
   1045 }
   1046 #endif
   1047 
   1048 
   1049 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
   1050   // Check for allocation failures during stub compilation.
   1051   if (failure_->IsFailure()) return failure_;
   1052 
   1053   // Create code object in the heap.
   1054   CodeDesc desc;
   1055   masm_.GetCode(&desc);
   1056   Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
   1057 #ifdef ENABLE_DISASSEMBLER
   1058   if (FLAG_print_code_stubs && !result->IsFailure()) {
   1059     Code::cast(result)->Disassemble(name);
   1060   }
   1061 #endif
   1062   return result;
   1063 }
   1064 
   1065 
   1066 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
   1067   if (FLAG_print_code_stubs && (name != NULL)) {
   1068     return GetCodeWithFlags(flags, *name->ToCString());
   1069   }
   1070   return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
   1071 }
   1072 
   1073 
   1074 void StubCompiler::LookupPostInterceptor(JSObject* holder,
   1075                                          String* name,
   1076                                          LookupResult* lookup) {
   1077   holder->LocalLookupRealNamedProperty(name, lookup);
   1078   if (!lookup->IsProperty()) {
   1079     lookup->NotFound();
   1080     Object* proto = holder->GetPrototype();
   1081     if (proto != Heap::null_value()) {
   1082       proto->Lookup(name, lookup);
   1083     }
   1084   }
   1085 }
   1086 
   1087 
   1088 
   1089 Object* LoadStubCompiler::GetCode(PropertyType type, String* name) {
   1090   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
   1091   return GetCodeWithFlags(flags, name);
   1092 }
   1093 
   1094 
   1095 Object* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
   1096   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
   1097   return GetCodeWithFlags(flags, name);
   1098 }
   1099 
   1100 
   1101 Object* StoreStubCompiler::GetCode(PropertyType type, String* name) {
   1102   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
   1103   return GetCodeWithFlags(flags, name);
   1104 }
   1105 
   1106 
   1107 Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
   1108   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
   1109   return GetCodeWithFlags(flags, name);
   1110 }
   1111 
   1112 
   1113 Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
   1114   int argc = arguments_.immediate();
   1115   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
   1116                                                     type,
   1117                                                     in_loop_,
   1118                                                     argc);
   1119   return GetCodeWithFlags(flags, name);
   1120 }
   1121 
   1122 
   1123 Object* ConstructStubCompiler::GetCode() {
   1124   Code::Flags flags = Code::ComputeFlags(Code::STUB);
   1125   Object* result = GetCodeWithFlags(flags, "ConstructStub");
   1126   if (!result->IsFailure()) {
   1127     Code* code = Code::cast(result);
   1128     USE(code);
   1129     LOG(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
   1130   }
   1131   return result;
   1132 }
   1133 
   1134 
   1135 } }  // namespace v8::internal
   1136