| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/v8.h" | 5 #include "src/v8.h" | 
| 6 | 6 | 
| 7 #include "src/api.h" | 7 #include "src/ic/ic-inl.h" | 
| 8 #include "src/arguments.h" | 8 #include "src/ic/ic-compiler.h" | 
| 9 #include "src/ast.h" | 9 | 
| 10 #include "src/code-stubs.h" |  | 
| 11 #include "src/cpu-profiler.h" |  | 
| 12 #include "src/gdb-jit.h" |  | 
| 13 #include "src/ic-inl.h" |  | 
| 14 #include "src/stub-cache.h" |  | 
| 15 #include "src/type-info.h" |  | 
| 16 #include "src/vm-state-inl.h" |  | 
| 17 | 10 | 
| 18 namespace v8 { | 11 namespace v8 { | 
| 19 namespace internal { | 12 namespace internal { | 
| 20 | 13 | 
| 21 // ----------------------------------------------------------------------- |  | 
| 22 // StubCache implementation. |  | 
| 23 |  | 
| 24 |  | 
| 25 StubCache::StubCache(Isolate* isolate) |  | 
| 26     : isolate_(isolate) { } |  | 
| 27 |  | 
| 28 |  | 
| 29 void StubCache::Initialize() { |  | 
| 30   DCHECK(IsPowerOf2(kPrimaryTableSize)); |  | 
| 31   DCHECK(IsPowerOf2(kSecondaryTableSize)); |  | 
| 32   Clear(); |  | 
| 33 } |  | 
| 34 |  | 
| 35 |  | 
| 36 static Code::Flags CommonStubCacheChecks(Name* name, Map* map, |  | 
| 37                                          Code::Flags flags) { |  | 
| 38   flags = Code::RemoveTypeAndHolderFromFlags(flags); |  | 
| 39 |  | 
| 40   // Validate that the name does not move on scavenge, and that we |  | 
| 41   // can use identity checks instead of structural equality checks. |  | 
| 42   DCHECK(!name->GetHeap()->InNewSpace(name)); |  | 
| 43   DCHECK(name->IsUniqueName()); |  | 
| 44 |  | 
| 45   // The state bits are not important to the hash function because the stub |  | 
| 46   // cache only contains handlers. Make sure that the bits are the least |  | 
| 47   // significant so they will be the ones masked out. |  | 
| 48   DCHECK_EQ(Code::HANDLER, Code::ExtractKindFromFlags(flags)); |  | 
| 49   STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1); |  | 
| 50 |  | 
| 51   // Make sure that the code type and cache holder are not included in the hash. |  | 
| 52   DCHECK(Code::ExtractTypeFromFlags(flags) == 0); |  | 
| 53   DCHECK(Code::ExtractCacheHolderFromFlags(flags) == 0); |  | 
| 54 |  | 
| 55   return flags; |  | 
| 56 } |  | 
| 57 |  | 
| 58 |  | 
| 59 Code* StubCache::Set(Name* name, Map* map, Code* code) { |  | 
| 60   Code::Flags flags = CommonStubCacheChecks(name, map, code->flags()); |  | 
| 61 |  | 
| 62   // Compute the primary entry. |  | 
| 63   int primary_offset = PrimaryOffset(name, flags, map); |  | 
| 64   Entry* primary = entry(primary_, primary_offset); |  | 
| 65   Code* old_code = primary->value; |  | 
| 66 |  | 
| 67   // If the primary entry has useful data in it, we retire it to the |  | 
| 68   // secondary cache before overwriting it. |  | 
| 69   if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { |  | 
| 70     Map* old_map = primary->map; |  | 
| 71     Code::Flags old_flags = |  | 
| 72         Code::RemoveTypeAndHolderFromFlags(old_code->flags()); |  | 
| 73     int seed = PrimaryOffset(primary->key, old_flags, old_map); |  | 
| 74     int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); |  | 
| 75     Entry* secondary = entry(secondary_, secondary_offset); |  | 
| 76     *secondary = *primary; |  | 
| 77   } |  | 
| 78 |  | 
| 79   // Update primary cache. |  | 
| 80   primary->key = name; |  | 
| 81   primary->value = code; |  | 
| 82   primary->map = map; |  | 
| 83   isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); |  | 
| 84   return code; |  | 
| 85 } |  | 
| 86 |  | 
| 87 |  | 
| 88 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { |  | 
| 89   flags = CommonStubCacheChecks(name, map, flags); |  | 
| 90   int primary_offset = PrimaryOffset(name, flags, map); |  | 
| 91   Entry* primary = entry(primary_, primary_offset); |  | 
| 92   if (primary->key == name && primary->map == map) { |  | 
| 93     return primary->value; |  | 
| 94   } |  | 
| 95   int secondary_offset = SecondaryOffset(name, flags, primary_offset); |  | 
| 96   Entry* secondary = entry(secondary_, secondary_offset); |  | 
| 97   if (secondary->key == name && secondary->map == map) { |  | 
| 98     return secondary->value; |  | 
| 99   } |  | 
| 100   return NULL; |  | 
| 101 } |  | 
| 102 |  | 
| 103 | 14 | 
| 104 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, | 15 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, | 
| 105                                       Handle<Map> stub_holder, Code::Kind kind, | 16                                       Handle<Map> stub_holder, Code::Kind kind, | 
| 106                                       ExtraICState extra_state, | 17                                       ExtraICState extra_state, | 
| 107                                       CacheHolderFlag cache_holder) { | 18                                       CacheHolderFlag cache_holder) { | 
| 108   Code::Flags flags = Code::ComputeMonomorphicFlags( | 19   Code::Flags flags = | 
| 109       kind, extra_state, cache_holder); | 20       Code::ComputeMonomorphicFlags(kind, extra_state, cache_holder); | 
| 110   Object* probe = stub_holder->FindInCodeCache(*name, flags); | 21   Object* probe = stub_holder->FindInCodeCache(*name, flags); | 
| 111   if (probe->IsCode()) return handle(Code::cast(probe)); | 22   if (probe->IsCode()) return handle(Code::cast(probe)); | 
| 112   return Handle<Code>::null(); | 23   return Handle<Code>::null(); | 
| 113 } | 24 } | 
| 114 | 25 | 
| 115 | 26 | 
| 116 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, | 27 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, | 
| 117                                            Handle<Map> stub_holder, | 28                                            Handle<Map> stub_holder, | 
| 118                                            Code::Kind kind, | 29                                            Code::Kind kind, | 
| 119                                            CacheHolderFlag cache_holder, | 30                                            CacheHolderFlag cache_holder, | 
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 254 | 165 | 
| 255   Handle<String> name = isolate->factory()->KeyedStoreMonomorphic_string(); | 166   Handle<String> name = isolate->factory()->KeyedStoreMonomorphic_string(); | 
| 256   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | 167   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | 
| 257   if (probe->IsCode()) return Handle<Code>::cast(probe); | 168   if (probe->IsCode()) return Handle<Code>::cast(probe); | 
| 258 | 169 | 
| 259   PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 170   PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 
| 260   Handle<Code> code = | 171   Handle<Code> code = | 
| 261       compiler.CompileKeyedStoreMonomorphic(receiver_map, store_mode); | 172       compiler.CompileKeyedStoreMonomorphic(receiver_map, store_mode); | 
| 262 | 173 | 
| 263   Map::UpdateCodeCache(receiver_map, name, code); | 174   Map::UpdateCodeCache(receiver_map, name, code); | 
| 264   DCHECK(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 175   DCHECK(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) == | 
| 265          == store_mode); | 176          store_mode); | 
| 266   return code; | 177   return code; | 
| 267 } | 178 } | 
| 268 | 179 | 
| 269 | 180 | 
| 270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 181 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 
| 271 | 182 | 
| 272 static void FillCache(Isolate* isolate, Handle<Code> code) { |  | 
| 273   Handle<UnseededNumberDictionary> dictionary = |  | 
| 274       UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |  | 
| 275                                     code->flags(), |  | 
| 276                                     code); |  | 
| 277   isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |  | 
| 278 } |  | 
| 279 |  | 
| 280 | 183 | 
| 281 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, | 184 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, | 
| 282                                              ExtraICState state) { | 185                                              ExtraICState state) { | 
| 283   Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 186   Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 
| 284   UnseededNumberDictionary* dictionary = | 187   UnseededNumberDictionary* dictionary = | 
| 285       isolate->heap()->non_monomorphic_cache(); | 188       isolate->heap()->non_monomorphic_cache(); | 
| 286   int entry = dictionary->FindEntry(isolate, flags); | 189   int entry = dictionary->FindEntry(isolate, flags); | 
| 287   DCHECK(entry != -1); | 190   DCHECK(entry != -1); | 
| 288   Object* code = dictionary->ValueAt(entry); | 191   Object* code = dictionary->ValueAt(entry); | 
| 289   // This might be called during the marking phase of the collector | 192   // This might be called during the marking phase of the collector | 
| 290   // hence the unchecked cast. | 193   // hence the unchecked cast. | 
| 291   return reinterpret_cast<Code*>(code); | 194   return reinterpret_cast<Code*>(code); | 
| 292 } | 195 } | 
| 293 | 196 | 
| 294 | 197 | 
|  | 198 static void FillCache(Isolate* isolate, Handle<Code> code) { | 
|  | 199   Handle<UnseededNumberDictionary> dictionary = UnseededNumberDictionary::Set( | 
|  | 200       isolate->factory()->non_monomorphic_cache(), code->flags(), code); | 
|  | 201   isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 
|  | 202 } | 
|  | 203 | 
|  | 204 | 
| 295 Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, | 205 Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, | 
| 296                                              InlineCacheState ic_state, | 206                                              InlineCacheState ic_state, | 
| 297                                              ExtraICState extra_state) { | 207                                              ExtraICState extra_state) { | 
| 298   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 208   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 
| 299   Handle<UnseededNumberDictionary> cache = | 209   Handle<UnseededNumberDictionary> cache = | 
| 300       isolate->factory()->non_monomorphic_cache(); | 210       isolate->factory()->non_monomorphic_cache(); | 
| 301   int entry = cache->FindEntry(isolate, flags); | 211   int entry = cache->FindEntry(isolate, flags); | 
| 302   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 212   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 
| 303 | 213 | 
| 304   PropertyICCompiler compiler(isolate, Code::LOAD_IC); | 214   PropertyICCompiler compiler(isolate, Code::LOAD_IC); | 
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 410 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( | 320 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( | 
| 411     MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, | 321     MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, | 
| 412     StrictMode strict_mode) { | 322     StrictMode strict_mode) { | 
| 413   Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 323   Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 
| 414   DCHECK(store_mode == STANDARD_STORE || | 324   DCHECK(store_mode == STANDARD_STORE || | 
| 415          store_mode == STORE_AND_GROW_NO_TRANSITION || | 325          store_mode == STORE_AND_GROW_NO_TRANSITION || | 
| 416          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 326          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 
| 417          store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 327          store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 
| 418   Handle<PolymorphicCodeCache> cache = | 328   Handle<PolymorphicCodeCache> cache = | 
| 419       isolate->factory()->polymorphic_code_cache(); | 329       isolate->factory()->polymorphic_code_cache(); | 
| 420   ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( | 330   ExtraICState extra_state = | 
| 421       strict_mode, store_mode); | 331       KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); | 
| 422   Code::Flags flags = | 332   Code::Flags flags = | 
| 423       Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 333       Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 
| 424   Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 334   Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 
| 425   if (probe->IsCode()) return Handle<Code>::cast(probe); | 335   if (probe->IsCode()) return Handle<Code>::cast(probe); | 
| 426 | 336 | 
| 427   PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 337   PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 
| 428   Handle<Code> code = | 338   Handle<Code> code = | 
| 429       compiler.CompileKeyedStorePolymorphic(receiver_maps, store_mode); | 339       compiler.CompileKeyedStorePolymorphic(receiver_maps, store_mode); | 
| 430   PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 340   PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 
| 431   return code; | 341   return code; | 
| 432 } | 342 } | 
| 433 | 343 | 
| 434 | 344 | 
| 435 void StubCache::Clear() { |  | 
| 436   Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |  | 
| 437   for (int i = 0; i < kPrimaryTableSize; i++) { |  | 
| 438     primary_[i].key = isolate()->heap()->empty_string(); |  | 
| 439     primary_[i].map = NULL; |  | 
| 440     primary_[i].value = empty; |  | 
| 441   } |  | 
| 442   for (int j = 0; j < kSecondaryTableSize; j++) { |  | 
| 443     secondary_[j].key = isolate()->heap()->empty_string(); |  | 
| 444     secondary_[j].map = NULL; |  | 
| 445     secondary_[j].value = empty; |  | 
| 446   } |  | 
| 447 } |  | 
| 448 |  | 
| 449 |  | 
| 450 void StubCache::CollectMatchingMaps(SmallMapList* types, |  | 
| 451                                     Handle<Name> name, |  | 
| 452                                     Code::Flags flags, |  | 
| 453                                     Handle<Context> native_context, |  | 
| 454                                     Zone* zone) { |  | 
| 455   for (int i = 0; i < kPrimaryTableSize; i++) { |  | 
| 456     if (primary_[i].key == *name) { |  | 
| 457       Map* map = primary_[i].map; |  | 
| 458       // Map can be NULL, if the stub is constant function call |  | 
| 459       // with a primitive receiver. |  | 
| 460       if (map == NULL) continue; |  | 
| 461 |  | 
| 462       int offset = PrimaryOffset(*name, flags, map); |  | 
| 463       if (entry(primary_, offset) == &primary_[i] && |  | 
| 464           !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { |  | 
| 465         types->AddMapIfMissing(Handle<Map>(map), zone); |  | 
| 466       } |  | 
| 467     } |  | 
| 468   } |  | 
| 469 |  | 
| 470   for (int i = 0; i < kSecondaryTableSize; i++) { |  | 
| 471     if (secondary_[i].key == *name) { |  | 
| 472       Map* map = secondary_[i].map; |  | 
| 473       // Map can be NULL, if the stub is constant function call |  | 
| 474       // with a primitive receiver. |  | 
| 475       if (map == NULL) continue; |  | 
| 476 |  | 
| 477       // Lookup in primary table and skip duplicates. |  | 
| 478       int primary_offset = PrimaryOffset(*name, flags, map); |  | 
| 479 |  | 
| 480       // Lookup in secondary table and add matches. |  | 
| 481       int offset = SecondaryOffset(*name, flags, primary_offset); |  | 
| 482       if (entry(secondary_, offset) == &secondary_[i] && |  | 
| 483           !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { |  | 
| 484         types->AddMapIfMissing(Handle<Map>(map), zone); |  | 
| 485       } |  | 
| 486     } |  | 
| 487   } |  | 
| 488 } |  | 
| 489 |  | 
| 490 |  | 
| 491 // ------------------------------------------------------------------------ |  | 
| 492 // StubCompiler implementation. |  | 
| 493 |  | 
| 494 |  | 
| 495 RUNTIME_FUNCTION(StoreCallbackProperty) { |  | 
| 496   Handle<JSObject> receiver = args.at<JSObject>(0); |  | 
| 497   Handle<JSObject> holder = args.at<JSObject>(1); |  | 
| 498   Handle<ExecutableAccessorInfo> callback = args.at<ExecutableAccessorInfo>(2); |  | 
| 499   Handle<Name> name = args.at<Name>(3); |  | 
| 500   Handle<Object> value = args.at<Object>(4); |  | 
| 501   HandleScope scope(isolate); |  | 
| 502 |  | 
| 503   DCHECK(callback->IsCompatibleReceiver(*receiver)); |  | 
| 504 |  | 
| 505   Address setter_address = v8::ToCData<Address>(callback->setter()); |  | 
| 506   v8::AccessorNameSetterCallback fun = |  | 
| 507       FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address); |  | 
| 508   DCHECK(fun != NULL); |  | 
| 509 |  | 
| 510   LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name)); |  | 
| 511   PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver, |  | 
| 512                                         *holder); |  | 
| 513   custom_args.Call(fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |  | 
| 514   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |  | 
| 515   return *value; |  | 
| 516 } |  | 
| 517 |  | 
| 518 |  | 
| 519 /** |  | 
| 520  * Attempts to load a property with an interceptor (which must be present), |  | 
| 521  * but doesn't search the prototype chain. |  | 
| 522  * |  | 
| 523  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't |  | 
| 524  * provide any value for the given name. |  | 
| 525  */ |  | 
| 526 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { |  | 
| 527   DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |  | 
| 528   Handle<Name> name_handle = |  | 
| 529       args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |  | 
| 530   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>( |  | 
| 531       NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex); |  | 
| 532 |  | 
| 533   // TODO(rossberg): Support symbols in the API. |  | 
| 534   if (name_handle->IsSymbol()) |  | 
| 535     return isolate->heap()->no_interceptor_result_sentinel(); |  | 
| 536   Handle<String> name = Handle<String>::cast(name_handle); |  | 
| 537 |  | 
| 538   Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); |  | 
| 539   v8::NamedPropertyGetterCallback getter = |  | 
| 540       FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address); |  | 
| 541   DCHECK(getter != NULL); |  | 
| 542 |  | 
| 543   Handle<JSObject> receiver = |  | 
| 544       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |  | 
| 545   Handle<JSObject> holder = |  | 
| 546       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |  | 
| 547   PropertyCallbackArguments callback_args( |  | 
| 548       isolate, interceptor_info->data(), *receiver, *holder); |  | 
| 549   { |  | 
| 550     // Use the interceptor getter. |  | 
| 551     HandleScope scope(isolate); |  | 
| 552     v8::Handle<v8::Value> r = |  | 
| 553         callback_args.Call(getter, v8::Utils::ToLocal(name)); |  | 
| 554     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |  | 
| 555     if (!r.IsEmpty()) { |  | 
| 556       Handle<Object> result = v8::Utils::OpenHandle(*r); |  | 
| 557       result->VerifyApiCallResultType(); |  | 
| 558       return *v8::Utils::OpenHandle(*r); |  | 
| 559     } |  | 
| 560   } |  | 
| 561 |  | 
| 562   return isolate->heap()->no_interceptor_result_sentinel(); |  | 
| 563 } |  | 
| 564 |  | 
| 565 |  | 
| 566 static Object* ThrowReferenceError(Isolate* isolate, Name* name) { |  | 
| 567   // If the load is non-contextual, just return the undefined result. |  | 
| 568   // Note that both keyed and non-keyed loads may end up here. |  | 
| 569   HandleScope scope(isolate); |  | 
| 570   LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |  | 
| 571   if (ic.contextual_mode() != CONTEXTUAL) { |  | 
| 572     return isolate->heap()->undefined_value(); |  | 
| 573   } |  | 
| 574 |  | 
| 575   // Throw a reference error. |  | 
| 576   Handle<Name> name_handle(name); |  | 
| 577   Handle<Object> error = |  | 
| 578       isolate->factory()->NewReferenceError("not_defined", |  | 
| 579                                             HandleVector(&name_handle, 1)); |  | 
| 580   return isolate->Throw(*error); |  | 
| 581 } |  | 
| 582 |  | 
| 583 |  | 
| 584 /** |  | 
| 585  * Loads a property with an interceptor performing post interceptor |  | 
| 586  * lookup if interceptor failed. |  | 
| 587  */ |  | 
| 588 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { |  | 
| 589   HandleScope scope(isolate); |  | 
| 590   DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |  | 
| 591   Handle<Name> name = |  | 
| 592       args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |  | 
| 593   Handle<JSObject> receiver = |  | 
| 594       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |  | 
| 595   Handle<JSObject> holder = |  | 
| 596       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |  | 
| 597 |  | 
| 598   Handle<Object> result; |  | 
| 599   LookupIterator it(receiver, name, holder); |  | 
| 600   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |  | 
| 601       isolate, result, JSObject::GetProperty(&it)); |  | 
| 602 |  | 
| 603   if (it.IsFound()) return *result; |  | 
| 604 |  | 
| 605   return ThrowReferenceError(isolate, Name::cast(args[0])); |  | 
| 606 } |  | 
| 607 |  | 
| 608 |  | 
| 609 RUNTIME_FUNCTION(StorePropertyWithInterceptor) { |  | 
| 610   HandleScope scope(isolate); |  | 
| 611   DCHECK(args.length() == 3); |  | 
| 612   StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |  | 
| 613   Handle<JSObject> receiver = args.at<JSObject>(0); |  | 
| 614   Handle<Name> name = args.at<Name>(1); |  | 
| 615   Handle<Object> value = args.at<Object>(2); |  | 
| 616 #ifdef DEBUG |  | 
| 617   PrototypeIterator iter(isolate, receiver, |  | 
| 618                          PrototypeIterator::START_AT_RECEIVER); |  | 
| 619   bool found = false; |  | 
| 620   while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |  | 
| 621     Handle<Object> current = PrototypeIterator::GetCurrent(iter); |  | 
| 622     if (current->IsJSObject() && |  | 
| 623         Handle<JSObject>::cast(current)->HasNamedInterceptor()) { |  | 
| 624       found = true; |  | 
| 625       break; |  | 
| 626     } |  | 
| 627   } |  | 
| 628   DCHECK(found); |  | 
| 629 #endif |  | 
| 630   Handle<Object> result; |  | 
| 631   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |  | 
| 632       isolate, result, |  | 
| 633       JSObject::SetProperty(receiver, name, value, ic.strict_mode())); |  | 
| 634   return *result; |  | 
| 635 } |  | 
| 636 |  | 
| 637 |  | 
| 638 RUNTIME_FUNCTION(LoadElementWithInterceptor) { |  | 
| 639   HandleScope scope(isolate); |  | 
| 640   Handle<JSObject> receiver = args.at<JSObject>(0); |  | 
| 641   DCHECK(args.smi_at(1) >= 0); |  | 
| 642   uint32_t index = args.smi_at(1); |  | 
| 643   Handle<Object> result; |  | 
| 644   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |  | 
| 645       isolate, result, |  | 
| 646       JSObject::GetElementWithInterceptor(receiver, receiver, index)); |  | 
| 647   return *result; |  | 
| 648 } |  | 
| 649 |  | 
| 650 |  | 
| 651 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { | 345 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { | 
| 652   LoadIC::GenerateInitialize(masm()); | 346   LoadIC::GenerateInitialize(masm()); | 
| 653   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 347   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 
| 654   PROFILE(isolate(), | 348   PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | 
| 655           CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |  | 
| 656   return code; | 349   return code; | 
| 657 } | 350 } | 
| 658 | 351 | 
| 659 | 352 | 
| 660 Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { | 353 Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { | 
| 661   LoadIC::GeneratePreMonomorphic(masm()); | 354   LoadIC::GeneratePreMonomorphic(masm()); | 
| 662   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); | 355   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); | 
| 663   PROFILE(isolate(), | 356   PROFILE(isolate(), | 
| 664           CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); | 357           CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); | 
| 665   return code; | 358   return code; | 
| 666 } | 359 } | 
| 667 | 360 | 
| 668 | 361 | 
| 669 Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) { | 362 Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) { | 
| 670   LoadIC::GenerateMegamorphic(masm()); | 363   LoadIC::GenerateMegamorphic(masm()); | 
| 671   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); | 364   Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); | 
| 672   PROFILE(isolate(), | 365   PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); | 
| 673           CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); |  | 
| 674   return code; | 366   return code; | 
| 675 } | 367 } | 
| 676 | 368 | 
| 677 | 369 | 
| 678 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { | 370 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { | 
| 679   StoreIC::GenerateInitialize(masm()); | 371   StoreIC::GenerateInitialize(masm()); | 
| 680   Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); | 372   Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); | 
| 681   PROFILE(isolate(), | 373   PROFILE(isolate(), CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); | 
| 682           CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); |  | 
| 683   return code; | 374   return code; | 
| 684 } | 375 } | 
| 685 | 376 | 
| 686 | 377 | 
| 687 Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) { | 378 Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) { | 
| 688   StoreIC::GeneratePreMonomorphic(masm()); | 379   StoreIC::GeneratePreMonomorphic(masm()); | 
| 689   Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); | 380   Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); | 
| 690   PROFILE(isolate(), | 381   PROFILE(isolate(), | 
| 691           CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); | 382           CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); | 
| 692   return code; | 383   return code; | 
| 693 } | 384 } | 
| 694 | 385 | 
| 695 | 386 | 
| 696 Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) { | 387 Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) { | 
| 697   ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 388   ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 
| 698   StrictMode strict_mode = StoreIC::GetStrictMode(extra_state); | 389   StrictMode strict_mode = StoreIC::GetStrictMode(extra_state); | 
| 699   StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); | 390   StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); | 
| 700   Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); | 391   Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); | 
| 701   PROFILE(isolate(), | 392   PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); | 
| 702           CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); |  | 
| 703   return code; | 393   return code; | 
| 704 } | 394 } | 
| 705 | 395 | 
| 706 | 396 | 
| 707 Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) { | 397 Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) { | 
| 708   StoreIC::GenerateMegamorphic(masm()); | 398   StoreIC::GenerateMegamorphic(masm()); | 
| 709   Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 399   Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 
| 710   PROFILE(isolate(), | 400   PROFILE(isolate(), CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); | 
| 711           CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); |  | 
| 712   return code; | 401   return code; | 
| 713 } | 402 } | 
| 714 | 403 | 
| 715 | 404 | 
| 716 #undef CALL_LOGGER_TAG | 405 #undef CALL_LOGGER_TAG | 
| 717 | 406 | 
| 718 | 407 | 
| 719 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, | 408 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, | 
| 720                                                       const char* name) { | 409                                                       const char* name) { | 
| 721   // Create code object in the heap. | 410   // Create code object in the heap. | 
| 722   CodeDesc desc; | 411   CodeDesc desc; | 
| 723   masm()->GetCode(&desc); | 412   masm()->GetCode(&desc); | 
| 724   Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject()); | 413   Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject()); | 
| 725   if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey()); | 414   if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey()); | 
| 726 #ifdef ENABLE_DISASSEMBLER | 415 #ifdef ENABLE_DISASSEMBLER | 
| 727   if (FLAG_print_code_stubs) { | 416   if (FLAG_print_code_stubs) { | 
| 728     OFStream os(stdout); | 417     OFStream os(stdout); | 
| 729     code->Disassemble(name, os); | 418     code->Disassemble(name, os); | 
| 730   } | 419   } | 
| 731 #endif | 420 #endif | 
| 732   return code; | 421   return code; | 
| 733 } | 422 } | 
| 734 | 423 | 
| 735 | 424 | 
| 736 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, | 425 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, | 
| 737                                                       Handle<Name> name) { | 426                                                       Handle<Name> name) { | 
| 738   return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) | 427   return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) | 
| 739       ? GetCodeWithFlags(flags, Handle<String>::cast(name)->ToCString().get()) | 428              ? GetCodeWithFlags(flags, | 
| 740       : GetCodeWithFlags(flags, NULL); | 429                                 Handle<String>::cast(name)->ToCString().get()) | 
|  | 430              : GetCodeWithFlags(flags, NULL); | 
| 741 } | 431 } | 
| 742 | 432 | 
| 743 | 433 | 
| 744 #define __ ACCESS_MASM(masm()) | 434 #define __ ACCESS_MASM(masm()) | 
| 745 | 435 | 
| 746 | 436 | 
| 747 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, | 437 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, | 
| 748                                                   Handle<Name> name, | 438                                                   Handle<Name> name, | 
| 749                                                   Label* miss) { | 439                                                   Label* miss) { | 
| 750   PrototypeCheckType check_type = CHECK_ALL_MAPS; | 440   PrototypeCheckType check_type = CHECK_ALL_MAPS; | 
| 751   int function_index = -1; | 441   int function_index = -1; | 
| 752   if (type()->Is(HeapType::String())) { | 442   if (type()->Is(HeapType::String())) { | 
| 753     function_index = Context::STRING_FUNCTION_INDEX; | 443     function_index = Context::STRING_FUNCTION_INDEX; | 
| 754   } else if (type()->Is(HeapType::Symbol())) { | 444   } else if (type()->Is(HeapType::Symbol())) { | 
| 755     function_index = Context::SYMBOL_FUNCTION_INDEX; | 445     function_index = Context::SYMBOL_FUNCTION_INDEX; | 
| 756   } else if (type()->Is(HeapType::Number())) { | 446   } else if (type()->Is(HeapType::Number())) { | 
| 757     function_index = Context::NUMBER_FUNCTION_INDEX; | 447     function_index = Context::NUMBER_FUNCTION_INDEX; | 
| 758   } else if (type()->Is(HeapType::Boolean())) { | 448   } else if (type()->Is(HeapType::Boolean())) { | 
| 759     function_index = Context::BOOLEAN_FUNCTION_INDEX; | 449     function_index = Context::BOOLEAN_FUNCTION_INDEX; | 
| 760   } else { | 450   } else { | 
| 761     check_type = SKIP_RECEIVER; | 451     check_type = SKIP_RECEIVER; | 
| 762   } | 452   } | 
| 763 | 453 | 
| 764   if (check_type == CHECK_ALL_MAPS) { | 454   if (check_type == CHECK_ALL_MAPS) { | 
| 765     GenerateDirectLoadGlobalFunctionPrototype( | 455     GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index, | 
| 766         masm(), function_index, scratch1(), miss); | 456                                               scratch1(), miss); | 
| 767     Object* function = isolate()->native_context()->get(function_index); | 457     Object* function = isolate()->native_context()->get(function_index); | 
| 768     Object* prototype = JSFunction::cast(function)->instance_prototype(); | 458     Object* prototype = JSFunction::cast(function)->instance_prototype(); | 
| 769     set_type_for_object(handle(prototype, isolate())); | 459     set_type_for_object(handle(prototype, isolate())); | 
| 770     object_reg = scratch1(); | 460     object_reg = scratch1(); | 
| 771   } | 461   } | 
| 772 | 462 | 
| 773   // Check that the maps starting from the prototype haven't changed. | 463   // Check that the maps starting from the prototype haven't changed. | 
| 774   return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, | 464   return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, | 
| 775                          miss, check_type); | 465                          miss, check_type); | 
| 776 } | 466 } | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 878   GenerateLoadCallback(reg, callback); | 568   GenerateLoadCallback(reg, callback); | 
| 879   return GetCode(kind(), Code::FAST, name); | 569   return GetCode(kind(), Code::FAST, name); | 
| 880 } | 570 } | 
| 881 | 571 | 
| 882 | 572 | 
| 883 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 573 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 
| 884     Handle<Name> name, const CallOptimization& call_optimization) { | 574     Handle<Name> name, const CallOptimization& call_optimization) { | 
| 885   DCHECK(call_optimization.is_simple_api_call()); | 575   DCHECK(call_optimization.is_simple_api_call()); | 
| 886   Frontend(receiver(), name); | 576   Frontend(receiver(), name); | 
| 887   Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); | 577   Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); | 
| 888   GenerateFastApiCall( | 578   GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), | 
| 889       masm(), call_optimization, receiver_map, | 579                       scratch1(), false, 0, NULL); | 
| 890       receiver(), scratch1(), false, 0, NULL); |  | 
| 891   return GetCode(kind(), Code::FAST, name); | 580   return GetCode(kind(), Code::FAST, name); | 
| 892 } | 581 } | 
| 893 | 582 | 
| 894 | 583 | 
| 895 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( | 584 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( | 
| 896     LookupIterator* it) { | 585     LookupIterator* it) { | 
| 897   // So far the most popular follow ups for interceptor loads are FIELD and | 586   // So far the most popular follow ups for interceptor loads are FIELD and | 
| 898   // ExecutableAccessorInfo, so inline only them. Other cases may be added | 587   // ExecutableAccessorInfo, so inline only them. Other cases may be added | 
| 899   // later. | 588   // later. | 
| 900   bool inline_followup = it->state() == LookupIterator::PROPERTY; | 589   bool inline_followup = it->state() == LookupIterator::PROPERTY; | 
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1026   GenerateStoreViaSetter(masm(), type(), receiver(), setter); | 715   GenerateStoreViaSetter(masm(), type(), receiver(), setter); | 
| 1027 | 716 | 
| 1028   return GetCode(kind(), Code::FAST, name); | 717   return GetCode(kind(), Code::FAST, name); | 
| 1029 } | 718 } | 
| 1030 | 719 | 
| 1031 | 720 | 
| 1032 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 721 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 
| 1033     Handle<JSObject> object, Handle<Name> name, | 722     Handle<JSObject> object, Handle<Name> name, | 
| 1034     const CallOptimization& call_optimization) { | 723     const CallOptimization& call_optimization) { | 
| 1035   Frontend(receiver(), name); | 724   Frontend(receiver(), name); | 
| 1036   Register values[] = { value() }; | 725   Register values[] = {value()}; | 
| 1037   GenerateFastApiCall( | 726   GenerateFastApiCall(masm(), call_optimization, handle(object->map()), | 
| 1038       masm(), call_optimization, handle(object->map()), | 727                       receiver(), scratch1(), true, 1, values); | 
| 1039       receiver(), scratch1(), true, 1, values); |  | 
| 1040   return GetCode(kind(), Code::FAST, name); | 728   return GetCode(kind(), Code::FAST, name); | 
| 1041 } | 729 } | 
| 1042 | 730 | 
| 1043 | 731 | 
| 1044 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( | 732 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( | 
| 1045     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { | 733     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { | 
| 1046   ElementsKind elements_kind = receiver_map->elements_kind(); | 734   ElementsKind elements_kind = receiver_map->elements_kind(); | 
| 1047   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 735   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 
| 1048   Handle<Code> stub; | 736   Handle<Code> stub; | 
| 1049   if (receiver_map->has_fast_elements() || | 737   if (receiver_map->has_fast_elements() || | 
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1191   KeyedStoreIC::GenerateSlow(masm); | 879   KeyedStoreIC::GenerateSlow(masm); | 
| 1192 } | 880 } | 
| 1193 | 881 | 
| 1194 | 882 | 
| 1195 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 883 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 
| 1196   Initialize(function); | 884   Initialize(function); | 
| 1197 } | 885 } | 
| 1198 | 886 | 
| 1199 | 887 | 
| 1200 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType( | 888 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType( | 
| 1201     Handle<Map> object_map, | 889     Handle<Map> object_map, HolderLookup* holder_lookup) const { | 
| 1202     HolderLookup* holder_lookup) const { |  | 
| 1203   DCHECK(is_simple_api_call()); | 890   DCHECK(is_simple_api_call()); | 
| 1204   if (!object_map->IsJSObjectMap()) { | 891   if (!object_map->IsJSObjectMap()) { | 
| 1205     *holder_lookup = kHolderNotFound; | 892     *holder_lookup = kHolderNotFound; | 
| 1206     return Handle<JSObject>::null(); | 893     return Handle<JSObject>::null(); | 
| 1207   } | 894   } | 
| 1208   if (expected_receiver_type_.is_null() || | 895   if (expected_receiver_type_.is_null() || | 
| 1209       expected_receiver_type_->IsTemplateFor(*object_map)) { | 896       expected_receiver_type_->IsTemplateFor(*object_map)) { | 
| 1210     *holder_lookup = kHolderIsReceiver; | 897     *holder_lookup = kHolderIsReceiver; | 
| 1211     return Handle<JSObject>::null(); | 898     return Handle<JSObject>::null(); | 
| 1212   } | 899   } | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 1224   return Handle<JSObject>::null(); | 911   return Handle<JSObject>::null(); | 
| 1225 } | 912 } | 
| 1226 | 913 | 
| 1227 | 914 | 
| 1228 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver, | 915 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver, | 
| 1229                                             Handle<JSObject> holder) const { | 916                                             Handle<JSObject> holder) const { | 
| 1230   DCHECK(is_simple_api_call()); | 917   DCHECK(is_simple_api_call()); | 
| 1231   if (!receiver->IsJSObject()) return false; | 918   if (!receiver->IsJSObject()) return false; | 
| 1232   Handle<Map> map(JSObject::cast(*receiver)->map()); | 919   Handle<Map> map(JSObject::cast(*receiver)->map()); | 
| 1233   HolderLookup holder_lookup; | 920   HolderLookup holder_lookup; | 
| 1234   Handle<JSObject> api_holder = | 921   Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup); | 
| 1235       LookupHolderOfExpectedType(map, &holder_lookup); |  | 
| 1236   switch (holder_lookup) { | 922   switch (holder_lookup) { | 
| 1237     case kHolderNotFound: | 923     case kHolderNotFound: | 
| 1238       return false; | 924       return false; | 
| 1239     case kHolderIsReceiver: | 925     case kHolderIsReceiver: | 
| 1240       return true; | 926       return true; | 
| 1241     case kHolderFound: | 927     case kHolderFound: | 
| 1242       if (api_holder.is_identical_to(holder)) return true; | 928       if (api_holder.is_identical_to(holder)) return true; | 
| 1243       // Check if holder is in prototype chain of api_holder. | 929       // Check if holder is in prototype chain of api_holder. | 
| 1244       { | 930       { | 
| 1245         JSObject* object = *api_holder; | 931         JSObject* object = *api_holder; | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1279   api_call_info_ = | 965   api_call_info_ = | 
| 1280       Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code())); | 966       Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code())); | 
| 1281 | 967 | 
| 1282   // Accept signatures that either have no restrictions at all or | 968   // Accept signatures that either have no restrictions at all or | 
| 1283   // only have restrictions on the receiver. | 969   // only have restrictions on the receiver. | 
| 1284   if (!info->signature()->IsUndefined()) { | 970   if (!info->signature()->IsUndefined()) { | 
| 1285     Handle<SignatureInfo> signature = | 971     Handle<SignatureInfo> signature = | 
| 1286         Handle<SignatureInfo>(SignatureInfo::cast(info->signature())); | 972         Handle<SignatureInfo>(SignatureInfo::cast(info->signature())); | 
| 1287     if (!signature->args()->IsUndefined()) return; | 973     if (!signature->args()->IsUndefined()) return; | 
| 1288     if (!signature->receiver()->IsUndefined()) { | 974     if (!signature->receiver()->IsUndefined()) { | 
| 1289       expected_receiver_type_ = | 975       expected_receiver_type_ = Handle<FunctionTemplateInfo>( | 
| 1290           Handle<FunctionTemplateInfo>( | 976           FunctionTemplateInfo::cast(signature->receiver())); | 
| 1291               FunctionTemplateInfo::cast(signature->receiver())); |  | 
| 1292     } | 977     } | 
| 1293   } | 978   } | 
| 1294 | 979 | 
| 1295   is_simple_api_call_ = true; | 980   is_simple_api_call_ = true; | 
| 1296 } | 981 } | 
| 1297 | 982 } | 
| 1298 | 983 }  // namespace v8::internal | 
| 1299 } }  // namespace v8::internal |  | 
| OLD | NEW | 
|---|