Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 return; | 251 return; |
| 252 } | 252 } |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 | 256 |
| 257 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, | 257 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, |
| 258 Handle<String> name) { | 258 Handle<String> name) { |
| 259 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; | 259 if (!IsNameCompatibleWithPrototypeFailure(name)) return false; |
| 260 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); | 260 Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate()); |
| 261 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | 261 if (UseVector()) { |
| 262 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map); | |
| 263 } else { | |
| 264 maybe_handler_ = target()->FindHandlerForMap(*receiver_map); | |
| 265 } | |
| 262 | 266 |
| 263 // The current map wasn't handled yet. There's no reason to stay monomorphic, | 267 // The current map wasn't handled yet. There's no reason to stay monomorphic, |
| 264 // *unless* we're moving from a deprecated map to its replacement, or | 268 // *unless* we're moving from a deprecated map to its replacement, or |
| 265 // to a more general elements kind. | 269 // to a more general elements kind. |
| 266 // TODO(verwaest): Check if the current map is actually what the old map | 270 // TODO(verwaest): Check if the current map is actually what the old map |
| 267 // would transition to. | 271 // would transition to. |
| 268 if (maybe_handler_.is_null()) { | 272 if (maybe_handler_.is_null()) { |
| 269 if (!receiver_map->IsJSObjectMap()) return false; | 273 if (!receiver_map->IsJSObjectMap()) return false; |
| 270 Map* first_map = FirstTargetMap(); | 274 Map* first_map = FirstTargetMap(); |
| 271 if (first_map == NULL) return false; | 275 if (first_map == NULL) return false; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 } | 307 } |
| 304 | 308 |
| 305 return true; | 309 return true; |
| 306 } | 310 } |
| 307 | 311 |
| 308 | 312 |
| 309 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { | 313 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) { |
| 310 if (target()->is_keyed_stub()) { | 314 if (target()->is_keyed_stub()) { |
| 311 // Determine whether the failure is due to a name failure. | 315 // Determine whether the failure is due to a name failure. |
| 312 if (!name->IsName()) return false; | 316 if (!name->IsName()) return false; |
| 313 Name* stub_name = target()->FindFirstName(); | 317 Name* stub_name = |
| 318 UseVector() ? nexus()->FindFirstName() : target()->FindFirstName(); | |
| 314 if (*name != stub_name) return false; | 319 if (*name != stub_name) return false; |
| 315 } | 320 } |
| 316 | 321 |
| 317 return true; | 322 return true; |
| 318 } | 323 } |
| 319 | 324 |
| 320 | 325 |
| 321 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { | 326 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { |
| 322 update_receiver_type(receiver); | 327 update_receiver_type(receiver); |
| 323 if (!name->IsString()) return; | 328 if (!name->IsString()) return; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 isolate->runtime_profiler()->NotifyICChanged(); | 450 isolate->runtime_profiler()->NotifyICChanged(); |
| 446 // TODO(2029): When an optimized function is patched, it would | 451 // TODO(2029): When an optimized function is patched, it would |
| 447 // be nice to propagate the corresponding type information to its | 452 // be nice to propagate the corresponding type information to its |
| 448 // unoptimized version for the benefit of later inlining. | 453 // unoptimized version for the benefit of later inlining. |
| 449 } | 454 } |
| 450 | 455 |
| 451 | 456 |
| 452 void IC::PostPatching(Address address, Code* target, Code* old_target) { | 457 void IC::PostPatching(Address address, Code* target, Code* old_target) { |
| 453 // Type vector based ICs update these statistics at a different time because | 458 // Type vector based ICs update these statistics at a different time because |
| 454 // they don't always patch on state change. | 459 // they don't always patch on state change. |
| 455 if (target->kind() == Code::CALL_IC) return; | 460 if (target->kind() == Code::CALL_IC || |
| 461 (FLAG_vector_ics && (target->kind() == Code::LOAD_IC || | |
|
Jakob Kummerow
2014/11/26 15:14:14
Can you re-use UseVector() here instead of duplica
mvstanton
2014/11/27 13:09:26
Done.
| |
| 462 target->kind() == Code::KEYED_LOAD_IC))) { | |
| 463 return; | |
| 464 } | |
| 456 | 465 |
| 457 Isolate* isolate = target->GetHeap()->isolate(); | 466 Isolate* isolate = target->GetHeap()->isolate(); |
| 458 State old_state = UNINITIALIZED; | 467 State old_state = UNINITIALIZED; |
| 459 State new_state = UNINITIALIZED; | 468 State new_state = UNINITIALIZED; |
| 460 bool target_remains_ic_stub = false; | 469 bool target_remains_ic_stub = false; |
| 461 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { | 470 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { |
| 462 old_state = old_target->ic_state(); | 471 old_state = old_target->ic_state(); |
| 463 new_state = target->ic_state(); | 472 new_state = target->ic_state(); |
| 464 target_remains_ic_stub = true; | 473 target_remains_ic_stub = true; |
| 465 } | 474 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 | 516 |
| 508 void IC::Clear(Isolate* isolate, Address address, | 517 void IC::Clear(Isolate* isolate, Address address, |
| 509 ConstantPoolArray* constant_pool) { | 518 ConstantPoolArray* constant_pool) { |
| 510 Code* target = GetTargetAtAddress(address, constant_pool); | 519 Code* target = GetTargetAtAddress(address, constant_pool); |
| 511 | 520 |
| 512 // Don't clear debug break inline cache as it will remove the break point. | 521 // Don't clear debug break inline cache as it will remove the break point. |
| 513 if (target->is_debug_stub()) return; | 522 if (target->is_debug_stub()) return; |
| 514 | 523 |
| 515 switch (target->kind()) { | 524 switch (target->kind()) { |
| 516 case Code::LOAD_IC: | 525 case Code::LOAD_IC: |
| 526 if (FLAG_vector_ics) return; | |
| 517 return LoadIC::Clear(isolate, address, target, constant_pool); | 527 return LoadIC::Clear(isolate, address, target, constant_pool); |
| 518 case Code::KEYED_LOAD_IC: | 528 case Code::KEYED_LOAD_IC: |
| 529 if (FLAG_vector_ics) return; | |
| 519 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 530 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); |
| 520 case Code::STORE_IC: | 531 case Code::STORE_IC: |
| 521 return StoreIC::Clear(isolate, address, target, constant_pool); | 532 return StoreIC::Clear(isolate, address, target, constant_pool); |
| 522 case Code::KEYED_STORE_IC: | 533 case Code::KEYED_STORE_IC: |
| 523 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 534 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
| 524 case Code::COMPARE_IC: | 535 case Code::COMPARE_IC: |
| 525 return CompareIC::Clear(isolate, address, target, constant_pool); | 536 return CompareIC::Clear(isolate, address, target, constant_pool); |
| 526 case Code::COMPARE_NIL_IC: | 537 case Code::COMPARE_NIL_IC: |
| 527 return CompareNilIC::Clear(address, target, constant_pool); | 538 return CompareNilIC::Clear(address, target, constant_pool); |
| 528 case Code::CALL_IC: // CallICs are vector-based and cleared differently. | 539 case Code::CALL_IC: // CallICs are vector-based and cleared differently. |
| 529 case Code::BINARY_OP_IC: | 540 case Code::BINARY_OP_IC: |
| 530 case Code::TO_BOOLEAN_IC: | 541 case Code::TO_BOOLEAN_IC: |
| 531 // Clearing these is tricky and does not | 542 // Clearing these is tricky and does not |
| 532 // make any performance difference. | 543 // make any performance difference. |
| 533 return; | 544 return; |
| 534 default: | 545 default: |
| 535 UNREACHABLE(); | 546 UNREACHABLE(); |
| 536 } | 547 } |
| 537 } | 548 } |
| 538 | 549 |
| 539 | 550 |
| 540 template <class Nexus> | |
| 541 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, Nexus* nexus) { | |
| 542 switch (kind) { | |
| 543 case Code::CALL_IC: | |
| 544 return CallIC::Clear(isolate, host, nexus); | |
| 545 default: | |
| 546 UNREACHABLE(); | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 | |
| 551 // Force instantiation of template instances for vector-based IC clearing. | |
| 552 template void IC::Clear(Isolate*, Code::Kind, Code*, CallICNexus*); | |
| 553 | |
| 554 | |
| 555 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 551 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, |
| 556 ConstantPoolArray* constant_pool) { | 552 ConstantPoolArray* constant_pool) { |
| 553 DCHECK(!FLAG_vector_ics); | |
| 557 if (IsCleared(target)) return; | 554 if (IsCleared(target)) return; |
| 558 | 555 |
| 559 // Make sure to also clear the map used in inline fast cases. If we | 556 // Make sure to also clear the map used in inline fast cases. If we |
| 560 // do not clear these maps, cached code can keep objects alive | 557 // do not clear these maps, cached code can keep objects alive |
| 561 // through the embedded maps. | 558 // through the embedded maps. |
| 562 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 559 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
| 563 } | 560 } |
| 564 | 561 |
| 565 | 562 |
| 563 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { | |
| 564 if (IsCleared(nexus)) return; | |
| 565 // Make sure to also clear the map used in inline fast cases. If we | |
| 566 // do not clear these maps, cached code can keep objects alive | |
| 567 // through the embedded maps. | |
| 568 State state = nexus->StateFromFeedback(); | |
| 569 nexus->ConfigurePremonomorphic(); | |
| 570 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | |
| 571 } | |
| 572 | |
| 573 | |
| 566 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 574 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { |
| 567 // Determine our state. | 575 // Determine our state. |
| 568 Object* feedback = nexus->vector()->Get(nexus->slot()); | 576 Object* feedback = nexus->vector()->Get(nexus->slot()); |
| 569 State state = nexus->StateFromFeedback(); | 577 State state = nexus->StateFromFeedback(); |
| 570 | 578 |
| 571 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 579 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
| 572 nexus->ConfigureUninitialized(); | 580 nexus->ConfigureUninitialized(); |
| 573 // The change in state must be processed. | 581 // The change in state must be processed. |
| 574 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 582 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); |
| 575 } | 583 } |
| 576 } | 584 } |
| 577 | 585 |
| 578 | 586 |
| 579 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | 587 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, |
| 580 ConstantPoolArray* constant_pool) { | 588 ConstantPoolArray* constant_pool) { |
| 589 DCHECK(!FLAG_vector_ics); | |
| 581 if (IsCleared(target)) return; | 590 if (IsCleared(target)) return; |
| 582 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, | 591 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, |
| 583 target->extra_ic_state()); | 592 target->extra_ic_state()); |
| 584 SetTargetAtAddress(address, code, constant_pool); | 593 SetTargetAtAddress(address, code, constant_pool); |
| 585 } | 594 } |
| 586 | 595 |
| 587 | 596 |
| 597 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { | |
| 598 if (IsCleared(nexus)) return; | |
| 599 // Determine our state. | |
|
Jakob Kummerow
2014/11/26 15:14:15
nit: I don't think this comment adds much value.
mvstanton
2014/11/27 13:09:26
Done.
| |
| 600 nexus->ConfigurePremonomorphic(); | |
| 601 State state = nexus->StateFromFeedback(); | |
|
Jakob Kummerow
2014/11/26 15:14:14
Save the previous state before calling ConfigurePr
mvstanton
2014/11/27 13:09:26
doh! good catch, thanks!
| |
| 602 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | |
| 603 } | |
| 604 | |
| 605 | |
| 588 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 606 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, |
| 589 ConstantPoolArray* constant_pool) { | 607 ConstantPoolArray* constant_pool) { |
| 590 if (IsCleared(target)) return; | 608 if (IsCleared(target)) return; |
| 591 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, | 609 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, |
| 592 target->extra_ic_state()); | 610 target->extra_ic_state()); |
| 593 SetTargetAtAddress(address, code, constant_pool); | 611 SetTargetAtAddress(address, code, constant_pool); |
| 594 } | 612 } |
| 595 | 613 |
| 596 | 614 |
| 597 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, | 615 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 628 | 646 |
| 629 static bool MigrateDeprecated(Handle<Object> object) { | 647 static bool MigrateDeprecated(Handle<Object> object) { |
| 630 if (!object->IsJSObject()) return false; | 648 if (!object->IsJSObject()) return false; |
| 631 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 649 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 632 if (!receiver->map()->is_deprecated()) return false; | 650 if (!receiver->map()->is_deprecated()) return false; |
| 633 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 651 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
| 634 return true; | 652 return true; |
| 635 } | 653 } |
| 636 | 654 |
| 637 | 655 |
| 656 void IC::ConfigureVectorState(IC::State new_state) { | |
| 657 DCHECK(UseVector()); | |
| 658 if (kind() == Code::LOAD_IC) { | |
| 659 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | |
| 660 if (new_state == PREMONOMORPHIC) { | |
| 661 nexus->ConfigurePremonomorphic(); | |
| 662 } else if (new_state == MEGAMORPHIC) { | |
| 663 nexus->ConfigureMegamorphic(); | |
| 664 } else { | |
| 665 UNREACHABLE(); | |
| 666 } | |
| 667 } else if (kind() == Code::KEYED_LOAD_IC) { | |
| 668 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | |
| 669 if (new_state == GENERIC) { | |
| 670 nexus->ConfigureGeneric(); | |
| 671 } else if (new_state == PREMONOMORPHIC) { | |
| 672 nexus->ConfigurePremonomorphic(); | |
| 673 } else if (new_state == MEGAMORPHIC) { | |
| 674 nexus->ConfigureMegamorphic(); | |
| 675 } else { | |
| 676 UNREACHABLE(); | |
| 677 } | |
| 678 } else { | |
| 679 UNREACHABLE(); | |
| 680 } | |
| 681 | |
| 682 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | |
| 683 new_state); | |
| 684 } | |
| 685 | |
| 686 | |
| 687 void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, | |
| 688 Handle<Code> handler) { | |
| 689 DCHECK(UseVector()); | |
| 690 if (kind() == Code::LOAD_IC) { | |
| 691 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | |
| 692 nexus->ConfigureMonomorphic(type, handler); | |
| 693 } else { | |
| 694 DCHECK(kind() == Code::KEYED_LOAD_IC); | |
| 695 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | |
| 696 nexus->ConfigureMonomorphic(name, type, handler); | |
| 697 } | |
| 698 | |
| 699 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | |
| 700 MONOMORPHIC); | |
| 701 } | |
| 702 | |
| 703 | |
| 704 void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types, | |
| 705 CodeHandleList* handlers) { | |
| 706 DCHECK(UseVector()); | |
| 707 if (kind() == Code::LOAD_IC) { | |
| 708 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | |
| 709 nexus->ConfigurePolymorphic(types, handlers); | |
| 710 } else { | |
| 711 DCHECK(kind() == Code::KEYED_LOAD_IC); | |
| 712 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | |
| 713 nexus->ConfigurePolymorphic(name, types, handlers); | |
| 714 } | |
| 715 | |
| 716 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | |
| 717 POLYMORPHIC); | |
| 718 } | |
| 719 | |
| 720 | |
| 638 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 721 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
| 639 // If the object is undefined or null it's illegal to try to get any | 722 // If the object is undefined or null it's illegal to try to get any |
| 640 // of its properties; throw a TypeError in that case. | 723 // of its properties; throw a TypeError in that case. |
| 641 if (object->IsUndefined() || object->IsNull()) { | 724 if (object->IsUndefined() || object->IsNull()) { |
| 642 return TypeError("non_object_property_load", object, name); | 725 return TypeError("non_object_property_load", object, name); |
| 643 } | 726 } |
| 644 | 727 |
| 645 // Check if the name is trivially convertible to an index and get | 728 // Check if the name is trivially convertible to an index and get |
| 646 // the element or char if so. | 729 // the element or char if so. |
| 647 uint32_t index; | 730 uint32_t index; |
| 648 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 731 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 649 // Rewrite to the generic keyed load stub. | 732 // Rewrite to the generic keyed load stub. |
| 650 if (FLAG_use_ic) { | 733 if (FLAG_use_ic) { |
| 651 set_target(*KeyedLoadIC::generic_stub(isolate())); | 734 if (UseVector()) { |
| 735 ConfigureVectorState(GENERIC); | |
| 736 } else { | |
| 737 set_target(*KeyedLoadIC::generic_stub(isolate())); | |
| 738 } | |
| 652 TRACE_IC("LoadIC", name); | 739 TRACE_IC("LoadIC", name); |
| 653 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 740 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
| 654 } | 741 } |
| 655 Handle<Object> result; | 742 Handle<Object> result; |
| 656 ASSIGN_RETURN_ON_EXCEPTION( | 743 ASSIGN_RETURN_ON_EXCEPTION( |
| 657 isolate(), result, | 744 isolate(), result, |
| 658 Runtime::GetElementOrCharAt(isolate(), object, index), Object); | 745 Runtime::GetElementOrCharAt(isolate(), object, index), Object); |
| 659 return result; | 746 return result; |
| 660 } | 747 } |
| 661 | 748 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 746 *type->AsClass()->Map())) { | 833 *type->AsClass()->Map())) { |
| 747 handler_to_overwrite = i; | 834 handler_to_overwrite = i; |
| 748 } | 835 } |
| 749 } | 836 } |
| 750 | 837 |
| 751 int number_of_valid_types = | 838 int number_of_valid_types = |
| 752 number_of_types - deprecated_types - (handler_to_overwrite != -1); | 839 number_of_types - deprecated_types - (handler_to_overwrite != -1); |
| 753 | 840 |
| 754 if (number_of_valid_types >= 4) return false; | 841 if (number_of_valid_types >= 4) return false; |
| 755 if (number_of_types == 0) return false; | 842 if (number_of_types == 0) return false; |
| 756 if (!target()->FindHandlers(&handlers, types.length())) return false; | 843 if (UseVector()) { |
| 844 if (!nexus()->FindHandlers(&handlers, types.length())) return false; | |
| 845 } else { | |
| 846 if (!target()->FindHandlers(&handlers, types.length())) return false; | |
| 847 } | |
| 757 | 848 |
| 758 number_of_valid_types++; | 849 number_of_valid_types++; |
| 759 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; | 850 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; |
| 760 Handle<Code> ic; | 851 Handle<Code> ic; |
| 761 if (number_of_valid_types == 1) { | 852 if (number_of_valid_types == 1) { |
| 762 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, | 853 if (UseVector()) { |
| 763 extra_ic_state()); | 854 DCHECK(kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC); |
|
Jakob Kummerow
2014/11/26 15:14:15
You can drop this DCHECK; ConfigureVectorState() c
mvstanton
2014/11/27 13:09:26
Done.
| |
| 855 ConfigureVectorState(name, receiver_type(), code); | |
| 856 } else { | |
| 857 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, | |
| 858 extra_ic_state()); | |
| 859 } | |
| 764 } else { | 860 } else { |
| 765 if (handler_to_overwrite >= 0) { | 861 if (handler_to_overwrite >= 0) { |
| 766 handlers.Set(handler_to_overwrite, code); | 862 handlers.Set(handler_to_overwrite, code); |
| 767 if (!type->NowIs(types.at(handler_to_overwrite))) { | 863 if (!type->NowIs(types.at(handler_to_overwrite))) { |
| 768 types.Set(handler_to_overwrite, type); | 864 types.Set(handler_to_overwrite, type); |
| 769 } | 865 } |
| 770 } else { | 866 } else { |
| 771 types.Add(type); | 867 types.Add(type); |
| 772 handlers.Add(code); | 868 handlers.Add(code); |
| 773 } | 869 } |
| 774 ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, | 870 |
| 775 number_of_valid_types, name, | 871 if (UseVector()) { |
| 776 extra_ic_state()); | 872 ConfigureVectorState(name, &types, &handlers); |
| 873 } else { | |
| 874 ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers, | |
| 875 number_of_valid_types, name, | |
| 876 extra_ic_state()); | |
| 877 } | |
| 777 } | 878 } |
| 778 set_target(*ic); | 879 |
| 880 if (!UseVector()) set_target(*ic); | |
| 779 return true; | 881 return true; |
| 780 } | 882 } |
| 781 | 883 |
| 782 | 884 |
| 783 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { | 885 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { |
| 784 return object->IsJSGlobalObject() | 886 return object->IsJSGlobalObject() |
| 785 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) | 887 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) |
| 786 : HeapType::NowOf(object, isolate); | 888 : HeapType::NowOf(object, isolate); |
| 787 } | 889 } |
| 788 | 890 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 816 | 918 |
| 817 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); | 919 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); |
| 818 | 920 |
| 819 | 921 |
| 820 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, | 922 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, |
| 821 Isolate* region); | 923 Isolate* region); |
| 822 | 924 |
| 823 | 925 |
| 824 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { | 926 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { |
| 825 DCHECK(handler->is_handler()); | 927 DCHECK(handler->is_handler()); |
| 826 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 928 if (UseVector()) { |
| 827 kind(), name, receiver_type(), handler, extra_ic_state()); | 929 ConfigureVectorState(name, receiver_type(), handler); |
| 828 set_target(*ic); | 930 } else { |
| 931 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | |
| 932 kind(), name, receiver_type(), handler, extra_ic_state()); | |
| 933 set_target(*ic); | |
| 934 } | |
| 829 } | 935 } |
| 830 | 936 |
| 831 | 937 |
| 832 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 938 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
| 833 TypeHandleList types; | 939 TypeHandleList types; |
| 834 CodeHandleList handlers; | 940 CodeHandleList handlers; |
| 835 TargetTypes(&types); | 941 TargetTypes(&types); |
| 836 if (!target()->FindHandlers(&handlers, types.length())) return; | 942 if (!target()->FindHandlers(&handlers, types.length())) return; |
| 837 for (int i = 0; i < types.length(); i++) { | 943 for (int i = 0; i < types.length(); i++) { |
| 838 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 944 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 863 break; | 969 break; |
| 864 case PROTOTYPE_FAILURE: | 970 case PROTOTYPE_FAILURE: |
| 865 case MONOMORPHIC: | 971 case MONOMORPHIC: |
| 866 case POLYMORPHIC: | 972 case POLYMORPHIC: |
| 867 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 973 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
| 868 if (UpdatePolymorphicIC(name, code)) break; | 974 if (UpdatePolymorphicIC(name, code)) break; |
| 869 // For keyed stubs, we can't know whether old handlers were for the | 975 // For keyed stubs, we can't know whether old handlers were for the |
| 870 // same key. | 976 // same key. |
| 871 CopyICToMegamorphicCache(name); | 977 CopyICToMegamorphicCache(name); |
| 872 } | 978 } |
| 873 set_target(*megamorphic_stub()); | 979 if (UseVector()) { |
| 980 ConfigureVectorState(MEGAMORPHIC); | |
| 981 } else { | |
| 982 set_target(*megamorphic_stub()); | |
| 983 } | |
| 874 // Fall through. | 984 // Fall through. |
| 875 case MEGAMORPHIC: | 985 case MEGAMORPHIC: |
| 876 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 986 UpdateMegamorphicCache(*receiver_type(), *name, *code); |
| 877 // Indicate that we've handled this case. | 987 // Indicate that we've handled this case. |
| 878 target_set_ = true; | 988 target_set_ = true; |
| 879 break; | 989 break; |
| 880 case DEBUG_STUB: | 990 case DEBUG_STUB: |
| 881 break; | 991 break; |
| 882 case DEFAULT: | 992 case DEFAULT: |
| 883 UNREACHABLE(); | 993 UNREACHABLE(); |
| 884 break; | 994 break; |
| 885 case GENERIC: | 995 case GENERIC: |
| 886 // The generic keyed store stub re-uses store handlers, which can miss. | 996 // The generic keyed store stub re-uses store handlers, which can miss. |
| 887 // That's ok, no reason to do anything. | 997 // That's ok, no reason to do anything. |
| 888 DCHECK(target()->kind() == Code::KEYED_STORE_IC); | 998 DCHECK(target()->kind() == Code::KEYED_STORE_IC); |
| 889 break; | 999 break; |
| 890 } | 1000 } |
| 891 } | 1001 } |
| 892 | 1002 |
| 893 | 1003 |
| 894 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 1004 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
| 895 ExtraICState extra_state) { | 1005 ExtraICState extra_state) { |
| 1006 if (FLAG_vector_ics) { | |
| 1007 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); | |
| 1008 } | |
| 1009 | |
| 896 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | 1010 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); |
| 897 } | 1011 } |
| 898 | 1012 |
| 899 | 1013 |
| 900 Handle<Code> LoadIC::initialize_stub_in_optimized_code( | 1014 Handle<Code> LoadIC::initialize_stub_in_optimized_code( |
| 901 Isolate* isolate, ExtraICState extra_state) { | 1015 Isolate* isolate, ExtraICState extra_state) { |
| 902 if (FLAG_vector_ics) { | 1016 if (FLAG_vector_ics) { |
| 903 return VectorLoadStub(isolate, LoadICState(extra_state)).GetCode(); | 1017 return VectorLoadStub(isolate, LoadICState(extra_state)).GetCode(); |
| 904 } | 1018 } |
| 905 return initialize_stub(isolate, extra_state); | 1019 return initialize_stub(isolate, extra_state); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 929 return stub.GetCode(); | 1043 return stub.GetCode(); |
| 930 } else { | 1044 } else { |
| 931 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 1045 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 932 return KeyedLoadIC::generic_stub(isolate()); | 1046 return KeyedLoadIC::generic_stub(isolate()); |
| 933 } | 1047 } |
| 934 } | 1048 } |
| 935 | 1049 |
| 936 | 1050 |
| 937 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 1051 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 938 ExtraICState extra_state) { | 1052 ExtraICState extra_state) { |
| 1053 DCHECK(!FLAG_vector_ics); | |
| 939 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 1054 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); |
| 940 } | 1055 } |
| 941 | 1056 |
| 942 | 1057 |
| 943 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { | 1058 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { |
| 944 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); | 1059 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); |
| 945 } | 1060 } |
| 946 | 1061 |
| 947 | 1062 |
| 948 Handle<Code> LoadIC::pre_monomorphic_stub() const { | 1063 Handle<Code> LoadIC::pre_monomorphic_stub() const { |
| 949 if (kind() == Code::LOAD_IC) { | 1064 if (kind() == Code::LOAD_IC) { |
| 950 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); | 1065 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); |
| 951 } else { | 1066 } else { |
| 952 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 1067 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 953 return KeyedLoadIC::pre_monomorphic_stub(isolate()); | 1068 return KeyedLoadIC::pre_monomorphic_stub(isolate()); |
| 954 } | 1069 } |
| 955 } | 1070 } |
| 956 | 1071 |
| 957 | 1072 |
| 958 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 1073 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
| 959 LoadFieldStub stub(isolate(), index); | 1074 LoadFieldStub stub(isolate(), index); |
| 960 return stub.GetCode(); | 1075 return stub.GetCode(); |
| 961 } | 1076 } |
| 962 | 1077 |
| 963 | 1078 |
| 964 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 1079 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
| 965 if (state() == UNINITIALIZED) { | 1080 if (state() == UNINITIALIZED) { |
| 966 // This is the first time we execute this inline cache. Set the target to | 1081 // This is the first time we execute this inline cache. Set the target to |
| 967 // the pre monomorphic stub to delay setting the monomorphic state. | 1082 // the pre monomorphic stub to delay setting the monomorphic state. |
| 968 set_target(*pre_monomorphic_stub()); | 1083 if (UseVector()) { |
| 1084 ConfigureVectorState(PREMONOMORPHIC); | |
| 1085 } else { | |
| 1086 set_target(*pre_monomorphic_stub()); | |
| 1087 } | |
| 969 TRACE_IC("LoadIC", lookup->name()); | 1088 TRACE_IC("LoadIC", lookup->name()); |
| 970 return; | 1089 return; |
| 971 } | 1090 } |
| 972 | 1091 |
| 973 Handle<Code> code; | 1092 Handle<Code> code; |
| 974 if (lookup->state() == LookupIterator::JSPROXY || | 1093 if (lookup->state() == LookupIterator::JSPROXY || |
| 975 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1094 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 976 code = slow_stub(); | 1095 code = slow_stub(); |
| 977 } else if (!lookup->IsFound()) { | 1096 } else if (!lookup->IsFound()) { |
| 978 if (kind() == Code::LOAD_IC) { | 1097 if (kind() == Code::LOAD_IC) { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1226 return key; | 1345 return key; |
| 1227 } | 1346 } |
| 1228 | 1347 |
| 1229 | 1348 |
| 1230 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 1349 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { |
| 1231 Handle<Map> receiver_map(receiver->map(), isolate()); | 1350 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1232 MapHandleList target_receiver_maps; | 1351 MapHandleList target_receiver_maps; |
| 1233 TargetMaps(&target_receiver_maps); | 1352 TargetMaps(&target_receiver_maps); |
| 1234 | 1353 |
| 1235 if (target_receiver_maps.length() == 0) { | 1354 if (target_receiver_maps.length() == 0) { |
| 1355 if (FLAG_vector_ics) { | |
| 1356 Handle<Code> handler = | |
| 1357 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | |
| 1358 ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); | |
| 1359 return target(); | |
|
Jakob Kummerow
2014/11/26 15:14:15
Consider "return Handle<Code>::null();" to make it
mvstanton
2014/11/27 13:09:26
I think this use of target() solved a problem for
| |
| 1360 } | |
| 1236 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1361 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
| 1237 } | 1362 } |
| 1238 | 1363 |
| 1239 // The first time a receiver is seen that is a transitioned version of the | 1364 // The first time a receiver is seen that is a transitioned version of the |
| 1240 // previous monomorphic receiver type, assume the new ElementsKind is the | 1365 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1241 // monomorphic type. This benefits global arrays that only transition | 1366 // monomorphic type. This benefits global arrays that only transition |
| 1242 // once, and all call sites accessing them are faster if they remain | 1367 // once, and all call sites accessing them are faster if they remain |
| 1243 // monomorphic. If this optimistic assumption is not true, the IC will | 1368 // monomorphic. If this optimistic assumption is not true, the IC will |
| 1244 // miss again and it will become polymorphic and support both the | 1369 // miss again and it will become polymorphic and support both the |
| 1245 // untransitioned and transitioned maps. | 1370 // untransitioned and transitioned maps. |
| 1246 if (state() == MONOMORPHIC && !receiver->IsString() && | 1371 if (state() == MONOMORPHIC && !receiver->IsString() && |
| 1247 IsMoreGeneralElementsKindTransition( | 1372 IsMoreGeneralElementsKindTransition( |
| 1248 target_receiver_maps.at(0)->elements_kind(), | 1373 target_receiver_maps.at(0)->elements_kind(), |
| 1249 Handle<JSObject>::cast(receiver)->GetElementsKind())) { | 1374 Handle<JSObject>::cast(receiver)->GetElementsKind())) { |
| 1375 if (FLAG_vector_ics) { | |
| 1376 Handle<Code> handler = | |
| 1377 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | |
| 1378 ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler); | |
| 1379 return target(); | |
| 1380 } | |
| 1250 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1381 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
| 1251 } | 1382 } |
| 1252 | 1383 |
| 1253 DCHECK(state() != GENERIC); | 1384 DCHECK(state() != GENERIC); |
| 1254 | 1385 |
| 1255 // Determine the list of receiver maps that this call site has seen, | 1386 // Determine the list of receiver maps that this call site has seen, |
| 1256 // adding the map that was just encountered. | 1387 // adding the map that was just encountered. |
| 1257 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1388 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
| 1258 // If the miss wasn't due to an unseen map, a polymorphic stub | 1389 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1259 // won't help, use the generic stub. | 1390 // won't help, use the generic stub. |
| 1260 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1391 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
| 1392 if (FLAG_vector_ics) { | |
| 1393 ConfigureVectorState(GENERIC); | |
| 1394 return target(); | |
| 1395 } | |
| 1261 return generic_stub(); | 1396 return generic_stub(); |
| 1262 } | 1397 } |
| 1263 | 1398 |
| 1264 // If the maximum number of receiver maps has been exceeded, use the generic | 1399 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1265 // version of the IC. | 1400 // version of the IC. |
| 1266 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1401 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1267 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1402 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1403 if (FLAG_vector_ics) { | |
| 1404 ConfigureVectorState(GENERIC); | |
| 1405 return target(); | |
| 1406 } | |
| 1268 return generic_stub(); | 1407 return generic_stub(); |
| 1269 } | 1408 } |
| 1270 | 1409 |
| 1410 if (FLAG_vector_ics) { | |
| 1411 CodeHandleList handlers(target_receiver_maps.length()); | |
| 1412 ElementHandlerCompiler compiler(isolate()); | |
| 1413 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | |
| 1414 TypeHandleList types(target_receiver_maps.length()); | |
| 1415 for (int i = 0; i < target_receiver_maps.length(); i++) { | |
| 1416 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); | |
| 1417 } | |
| 1418 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); | |
| 1419 return target(); | |
| 1420 } | |
| 1421 | |
| 1271 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 1422 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
| 1272 } | 1423 } |
| 1273 | 1424 |
| 1274 | 1425 |
| 1275 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1426 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
| 1276 Handle<Object> key) { | 1427 Handle<Object> key) { |
| 1277 if (MigrateDeprecated(object)) { | 1428 if (MigrateDeprecated(object)) { |
| 1278 Handle<Object> result; | 1429 Handle<Object> result; |
| 1279 ASSIGN_RETURN_ON_EXCEPTION( | 1430 ASSIGN_RETURN_ON_EXCEPTION( |
| 1280 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), | 1431 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1296 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1447 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1297 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1448 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
| 1298 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1449 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
| 1299 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { | 1450 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { |
| 1300 stub = LoadElementStub(receiver); | 1451 stub = LoadElementStub(receiver); |
| 1301 } | 1452 } |
| 1302 } | 1453 } |
| 1303 } | 1454 } |
| 1304 | 1455 |
| 1305 if (!is_target_set()) { | 1456 if (!is_target_set()) { |
| 1306 Code* generic = *generic_stub(); | 1457 if (!FLAG_vector_ics) { |
| 1307 if (*stub == generic) { | 1458 Code* generic = *generic_stub(); |
| 1308 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1459 if (*stub == generic) { |
| 1460 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | |
| 1461 } | |
| 1462 | |
| 1463 set_target(*stub); | |
| 1309 } | 1464 } |
| 1310 set_target(*stub); | |
| 1311 TRACE_IC("LoadIC", key); | 1465 TRACE_IC("LoadIC", key); |
| 1312 } | 1466 } |
| 1313 | 1467 |
| 1314 if (!load_handle.is_null()) return load_handle; | 1468 if (!load_handle.is_null()) return load_handle; |
| 1315 Handle<Object> result; | 1469 Handle<Object> result; |
| 1316 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 1470 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| 1317 Runtime::GetObjectProperty(isolate(), object, key), | 1471 Runtime::GetObjectProperty(isolate(), object, key), |
| 1318 Object); | 1472 Object); |
| 1319 return result; | 1473 return result; |
| 1320 } | 1474 } |
| (...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2151 CallIC ic(isolate, &nexus); | 2305 CallIC ic(isolate, &nexus); |
| 2152 ic.PatchMegamorphic(function); | 2306 ic.PatchMegamorphic(function); |
| 2153 return *function; | 2307 return *function; |
| 2154 } | 2308 } |
| 2155 | 2309 |
| 2156 | 2310 |
| 2157 // Used from ic-<arch>.cc. | 2311 // Used from ic-<arch>.cc. |
| 2158 RUNTIME_FUNCTION(LoadIC_Miss) { | 2312 RUNTIME_FUNCTION(LoadIC_Miss) { |
| 2159 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2313 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2160 HandleScope scope(isolate); | 2314 HandleScope scope(isolate); |
| 2161 DCHECK(args.length() == 2); | |
| 2162 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2163 Handle<Object> receiver = args.at<Object>(0); | 2315 Handle<Object> receiver = args.at<Object>(0); |
| 2164 Handle<Name> key = args.at<Name>(1); | 2316 Handle<Name> key = args.at<Name>(1); |
| 2165 ic.UpdateState(receiver, key); | |
| 2166 Handle<Object> result; | 2317 Handle<Object> result; |
| 2167 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2318 |
| 2319 if (args.length() == 4) { | |
| 2320 DCHECK(FLAG_vector_ics); | |
|
Jakob Kummerow
2014/11/26 15:14:14
I think I'd swap this around:
if (FLAG_vector_ics
mvstanton
2014/11/27 13:09:26
Cool. This is a relic of a time in the work when b
| |
| 2321 Handle<Smi> slot = args.at<Smi>(2); | |
| 2322 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | |
| 2323 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | |
| 2324 LoadICNexus nexus(vector, vector_slot); | |
| 2325 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | |
| 2326 ic.UpdateState(receiver, key); | |
| 2327 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2328 } else { | |
| 2329 DCHECK(args.length() == 2); | |
| 2330 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2331 ic.UpdateState(receiver, key); | |
| 2332 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2333 } | |
| 2168 return *result; | 2334 return *result; |
| 2169 } | 2335 } |
| 2170 | 2336 |
| 2171 | 2337 |
| 2172 // Used from ic-<arch>.cc | 2338 // Used from ic-<arch>.cc |
| 2173 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 2339 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { |
| 2174 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2340 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2175 HandleScope scope(isolate); | 2341 HandleScope scope(isolate); |
| 2176 DCHECK(args.length() == 2); | |
| 2177 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2178 Handle<Object> receiver = args.at<Object>(0); | 2342 Handle<Object> receiver = args.at<Object>(0); |
| 2179 Handle<Object> key = args.at<Object>(1); | 2343 Handle<Object> key = args.at<Object>(1); |
| 2180 ic.UpdateState(receiver, key); | |
| 2181 Handle<Object> result; | 2344 Handle<Object> result; |
| 2182 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2345 |
| 2346 if (args.length() == 4) { | |
| 2347 DCHECK(FLAG_vector_ics); | |
|
Jakob Kummerow
2014/11/26 15:14:15
again
mvstanton
2014/11/27 13:09:26
Done.
| |
| 2348 Handle<Smi> slot = args.at<Smi>(2); | |
| 2349 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | |
| 2350 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | |
| 2351 KeyedLoadICNexus nexus(vector, vector_slot); | |
| 2352 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | |
| 2353 ic.UpdateState(receiver, key); | |
| 2354 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2355 } else { | |
| 2356 DCHECK(args.length() == 2); | |
| 2357 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2358 ic.UpdateState(receiver, key); | |
| 2359 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2360 } | |
| 2361 | |
| 2183 return *result; | 2362 return *result; |
| 2184 } | 2363 } |
| 2185 | 2364 |
| 2186 | 2365 |
| 2187 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { | 2366 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { |
| 2188 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2367 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2189 HandleScope scope(isolate); | 2368 HandleScope scope(isolate); |
| 2190 DCHECK(args.length() == 2); | |
| 2191 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2192 Handle<Object> receiver = args.at<Object>(0); | 2369 Handle<Object> receiver = args.at<Object>(0); |
| 2193 Handle<Object> key = args.at<Object>(1); | 2370 Handle<Object> key = args.at<Object>(1); |
| 2194 ic.UpdateState(receiver, key); | |
| 2195 Handle<Object> result; | 2371 Handle<Object> result; |
| 2196 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2372 |
| 2373 if (args.length() == 4) { | |
| 2374 DCHECK(FLAG_vector_ics); | |
|
Jakob Kummerow
2014/11/26 15:14:14
again
mvstanton
2014/11/27 13:09:26
Done.
| |
| 2375 Handle<Smi> slot = args.at<Smi>(2); | |
| 2376 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | |
| 2377 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | |
| 2378 KeyedLoadICNexus nexus(vector, vector_slot); | |
| 2379 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | |
| 2380 ic.UpdateState(receiver, key); | |
| 2381 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2382 } else { | |
| 2383 DCHECK(args.length() == 2); | |
| 2384 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2385 ic.UpdateState(receiver, key); | |
| 2386 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2387 } | |
| 2388 | |
| 2197 return *result; | 2389 return *result; |
| 2198 } | 2390 } |
| 2199 | 2391 |
| 2200 | 2392 |
| 2201 // Used from ic-<arch>.cc. | 2393 // Used from ic-<arch>.cc. |
| 2202 RUNTIME_FUNCTION(StoreIC_Miss) { | 2394 RUNTIME_FUNCTION(StoreIC_Miss) { |
| 2203 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2395 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2204 HandleScope scope(isolate); | 2396 HandleScope scope(isolate); |
| 2205 DCHECK(args.length() == 3); | 2397 DCHECK(args.length() == 3); |
| 2206 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2398 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2678 } | 2870 } |
| 2679 | 2871 |
| 2680 return isolate->heap()->no_interceptor_result_sentinel(); | 2872 return isolate->heap()->no_interceptor_result_sentinel(); |
| 2681 } | 2873 } |
| 2682 | 2874 |
| 2683 | 2875 |
| 2684 static Object* ThrowReferenceError(Isolate* isolate, Name* name) { | 2876 static Object* ThrowReferenceError(Isolate* isolate, Name* name) { |
| 2685 // If the load is non-contextual, just return the undefined result. | 2877 // If the load is non-contextual, just return the undefined result. |
| 2686 // Note that both keyed and non-keyed loads may end up here. | 2878 // Note that both keyed and non-keyed loads may end up here. |
| 2687 HandleScope scope(isolate); | 2879 HandleScope scope(isolate); |
| 2688 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2880 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, true); |
| 2689 if (ic.contextual_mode() != CONTEXTUAL) { | 2881 if (ic.contextual_mode() != CONTEXTUAL) { |
| 2690 return isolate->heap()->undefined_value(); | 2882 return isolate->heap()->undefined_value(); |
| 2691 } | 2883 } |
| 2692 | 2884 |
| 2693 // Throw a reference error. | 2885 // Throw a reference error. |
| 2694 Handle<Name> name_handle(name); | 2886 Handle<Name> name_handle(name); |
| 2695 THROW_NEW_ERROR_RETURN_FAILURE( | 2887 THROW_NEW_ERROR_RETURN_FAILURE( |
| 2696 isolate, NewReferenceError("not_defined", HandleVector(&name_handle, 1))); | 2888 isolate, NewReferenceError("not_defined", HandleVector(&name_handle, 1))); |
| 2697 } | 2889 } |
| 2698 | 2890 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2760 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2952 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2761 isolate, result, | 2953 isolate, result, |
| 2762 JSObject::GetElementWithInterceptor(receiver, receiver, index)); | 2954 JSObject::GetElementWithInterceptor(receiver, receiver, index)); |
| 2763 return *result; | 2955 return *result; |
| 2764 } | 2956 } |
| 2765 | 2957 |
| 2766 | 2958 |
| 2767 RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { | 2959 RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { |
| 2768 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2960 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2769 HandleScope scope(isolate); | 2961 HandleScope scope(isolate); |
| 2770 DCHECK(args.length() == 2); | |
| 2771 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2772 Handle<Object> receiver = args.at<Object>(0); | 2962 Handle<Object> receiver = args.at<Object>(0); |
| 2773 Handle<Name> key = args.at<Name>(1); | 2963 Handle<Name> key = args.at<Name>(1); |
| 2774 ic.UpdateState(receiver, key); | |
| 2775 Handle<Object> result; | 2964 Handle<Object> result; |
| 2776 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2965 |
| 2966 if (args.length() == 4) { | |
| 2967 DCHECK(FLAG_vector_ics); | |
|
Jakob Kummerow
2014/11/26 15:14:14
again
mvstanton
2014/11/27 13:09:26
Done.
| |
| 2968 Handle<Smi> slot = args.at<Smi>(2); | |
| 2969 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | |
| 2970 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | |
| 2971 LoadICNexus nexus(vector, vector_slot); | |
| 2972 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | |
| 2973 ic.UpdateState(receiver, key); | |
| 2974 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2975 } else { | |
| 2976 DCHECK(args.length() == 2); | |
| 2977 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2978 ic.UpdateState(receiver, key); | |
| 2979 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2980 } | |
| 2981 | |
| 2777 return *result; | 2982 return *result; |
| 2778 } | 2983 } |
| 2779 | 2984 |
| 2780 | 2985 |
| 2781 static const Address IC_utilities[] = { | 2986 static const Address IC_utilities[] = { |
| 2782 #define ADDR(name) FUNCTION_ADDR(name), | 2987 #define ADDR(name) FUNCTION_ADDR(name), |
| 2783 IC_UTIL_LIST(ADDR) NULL | 2988 IC_UTIL_LIST(ADDR) NULL |
| 2784 #undef ADDR | 2989 #undef ADDR |
| 2785 }; | 2990 }; |
| 2786 | 2991 |
| 2787 | 2992 |
| 2788 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2993 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 2789 } | 2994 } |
| 2790 } // namespace v8::internal | 2995 } // namespace v8::internal |
| OLD | NEW |