| 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 |