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" |
11 #include "src/codegen.h" | 11 #include "src/codegen.h" |
12 #include "src/conversions.h" | 12 #include "src/conversions.h" |
13 #include "src/execution.h" | 13 #include "src/execution.h" |
14 #include "src/ic/call-optimization.h" | 14 #include "src/ic/call-optimization.h" |
15 #include "src/ic/handler-compiler.h" | 15 #include "src/ic/handler-compiler.h" |
16 #include "src/ic/ic-inl.h" | 16 #include "src/ic/ic-inl.h" |
17 #include "src/ic/ic-compiler.h" | 17 #include "src/ic/ic-compiler.h" |
18 #include "src/ic/stub-cache.h" | 18 #include "src/ic/stub-cache.h" |
| 19 #include "src/macro-assembler.h" |
19 #include "src/prototype.h" | 20 #include "src/prototype.h" |
20 #include "src/runtime/runtime.h" | 21 #include "src/runtime/runtime.h" |
21 | 22 |
22 namespace v8 { | 23 namespace v8 { |
23 namespace internal { | 24 namespace internal { |
24 | 25 |
25 char IC::TransitionMarkFromState(IC::State state) { | 26 char IC::TransitionMarkFromState(IC::State state) { |
26 switch (state) { | 27 switch (state) { |
27 case UNINITIALIZED: | 28 case UNINITIALIZED: |
28 return '0'; | 29 return '0'; |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 Code* target = GetTargetAtAddress(address, constant_pool); | 482 Code* target = GetTargetAtAddress(address, constant_pool); |
482 | 483 |
483 // Don't clear debug break inline cache as it will remove the break point. | 484 // Don't clear debug break inline cache as it will remove the break point. |
484 if (target->is_debug_stub()) return; | 485 if (target->is_debug_stub()) return; |
485 | 486 |
486 switch (target->kind()) { | 487 switch (target->kind()) { |
487 case Code::LOAD_IC: | 488 case Code::LOAD_IC: |
488 case Code::KEYED_LOAD_IC: | 489 case Code::KEYED_LOAD_IC: |
489 return; | 490 return; |
490 case Code::STORE_IC: | 491 case Code::STORE_IC: |
| 492 if (FLAG_vector_stores) return; |
491 return StoreIC::Clear(isolate, address, target, constant_pool); | 493 return StoreIC::Clear(isolate, address, target, constant_pool); |
492 case Code::KEYED_STORE_IC: | 494 case Code::KEYED_STORE_IC: |
| 495 if (FLAG_vector_stores) return; |
493 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 496 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
494 case Code::COMPARE_IC: | 497 case Code::COMPARE_IC: |
495 return CompareIC::Clear(isolate, address, target, constant_pool); | 498 return CompareIC::Clear(isolate, address, target, constant_pool); |
496 case Code::COMPARE_NIL_IC: | 499 case Code::COMPARE_NIL_IC: |
497 return CompareNilIC::Clear(address, target, constant_pool); | 500 return CompareNilIC::Clear(address, target, constant_pool); |
498 case Code::CALL_IC: // CallICs are vector-based and cleared differently. | 501 case Code::CALL_IC: // CallICs are vector-based and cleared differently. |
499 case Code::BINARY_OP_IC: | 502 case Code::BINARY_OP_IC: |
500 case Code::TO_BOOLEAN_IC: | 503 case Code::TO_BOOLEAN_IC: |
501 // Clearing these is tricky and does not | 504 // Clearing these is tricky and does not |
502 // make any performance difference. | 505 // make any performance difference. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 | 544 |
542 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 545 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, |
543 Address constant_pool) { | 546 Address constant_pool) { |
544 if (IsCleared(target)) return; | 547 if (IsCleared(target)) return; |
545 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, | 548 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, |
546 target->extra_ic_state()); | 549 target->extra_ic_state()); |
547 SetTargetAtAddress(address, code, constant_pool); | 550 SetTargetAtAddress(address, code, constant_pool); |
548 } | 551 } |
549 | 552 |
550 | 553 |
| 554 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { |
| 555 if (IsCleared(nexus)) return; |
| 556 State state = nexus->StateFromFeedback(); |
| 557 nexus->ConfigurePremonomorphic(); |
| 558 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); |
| 559 } |
| 560 |
| 561 |
551 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, | 562 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, |
552 Address constant_pool) { | 563 Address constant_pool) { |
553 if (IsCleared(target)) return; | 564 if (IsCleared(target)) return; |
554 Handle<Code> code = pre_monomorphic_stub( | 565 Handle<Code> code = pre_monomorphic_stub( |
555 isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); | 566 isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); |
556 SetTargetAtAddress(address, *code, constant_pool); | 567 SetTargetAtAddress(address, *code, constant_pool); |
557 } | 568 } |
558 | 569 |
559 | 570 |
| 571 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, |
| 572 KeyedStoreICNexus* nexus) { |
| 573 if (IsCleared(nexus)) return; |
| 574 State state = nexus->StateFromFeedback(); |
| 575 nexus->ConfigurePremonomorphic(); |
| 576 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); |
| 577 } |
| 578 |
| 579 |
560 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, | 580 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, |
561 Address constant_pool) { | 581 Address constant_pool) { |
562 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); | 582 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); |
563 CompareICStub stub(target->stub_key(), isolate); | 583 CompareICStub stub(target->stub_key(), isolate); |
564 // Only clear CompareICs that can retain objects. | 584 // Only clear CompareICs that can retain objects. |
565 if (stub.state() != CompareICState::KNOWN_OBJECT) return; | 585 if (stub.state() != CompareICState::KNOWN_OBJECT) return; |
566 SetTargetAtAddress(address, | 586 SetTargetAtAddress(address, |
567 GetRawUninitialized(isolate, stub.op(), stub.strength()), | 587 GetRawUninitialized(isolate, stub.op(), stub.strength()), |
568 constant_pool); | 588 constant_pool); |
569 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 589 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
(...skipping 14 matching lines...) Expand all Loading... |
584 if (!object->IsJSObject()) return false; | 604 if (!object->IsJSObject()) return false; |
585 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 605 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
586 if (!receiver->map()->is_deprecated()) return false; | 606 if (!receiver->map()->is_deprecated()) return false; |
587 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 607 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
588 return true; | 608 return true; |
589 } | 609 } |
590 | 610 |
591 | 611 |
592 void IC::ConfigureVectorState(IC::State new_state) { | 612 void IC::ConfigureVectorState(IC::State new_state) { |
593 DCHECK(UseVector()); | 613 DCHECK(UseVector()); |
594 if (kind() == Code::LOAD_IC) { | 614 if (new_state == PREMONOMORPHIC) { |
595 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 615 nexus()->ConfigurePremonomorphic(); |
596 if (new_state == PREMONOMORPHIC) { | 616 } else if (new_state == MEGAMORPHIC) { |
597 nexus->ConfigurePremonomorphic(); | 617 nexus()->ConfigureMegamorphic(); |
598 } else if (new_state == MEGAMORPHIC) { | |
599 nexus->ConfigureMegamorphic(); | |
600 } else { | |
601 UNREACHABLE(); | |
602 } | |
603 } else if (kind() == Code::KEYED_LOAD_IC) { | |
604 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | |
605 if (new_state == PREMONOMORPHIC) { | |
606 nexus->ConfigurePremonomorphic(); | |
607 } else if (new_state == MEGAMORPHIC) { | |
608 nexus->ConfigureMegamorphic(); | |
609 } else { | |
610 UNREACHABLE(); | |
611 } | |
612 } else { | 618 } else { |
613 UNREACHABLE(); | 619 UNREACHABLE(); |
614 } | 620 } |
615 | 621 |
616 vector_set_ = true; | 622 vector_set_ = true; |
617 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 623 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
618 new_state); | 624 new_state); |
619 } | 625 } |
620 | 626 |
621 | 627 |
622 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 628 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
623 Handle<Code> handler) { | 629 Handle<Code> handler) { |
624 DCHECK(UseVector()); | 630 DCHECK(UseVector()); |
625 if (kind() == Code::LOAD_IC) { | 631 if (kind() == Code::LOAD_IC) { |
626 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 632 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
627 nexus->ConfigureMonomorphic(map, handler); | 633 nexus->ConfigureMonomorphic(map, handler); |
| 634 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 635 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 636 nexus->ConfigureMonomorphic(name, map, handler); |
| 637 } else if (kind() == Code::STORE_IC) { |
| 638 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
| 639 nexus->ConfigureMonomorphic(map, handler); |
628 } else { | 640 } else { |
629 DCHECK(kind() == Code::KEYED_LOAD_IC); | 641 DCHECK(kind() == Code::KEYED_STORE_IC); |
630 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 642 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
631 nexus->ConfigureMonomorphic(name, map, handler); | 643 nexus->ConfigureMonomorphic(name, map, handler); |
632 } | 644 } |
633 | 645 |
634 vector_set_ = true; | 646 vector_set_ = true; |
635 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 647 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
636 MONOMORPHIC); | 648 MONOMORPHIC); |
637 } | 649 } |
638 | 650 |
639 | 651 |
640 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 652 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
641 CodeHandleList* handlers) { | 653 CodeHandleList* handlers) { |
642 DCHECK(UseVector()); | 654 DCHECK(UseVector()); |
643 if (kind() == Code::LOAD_IC) { | 655 if (kind() == Code::LOAD_IC) { |
644 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 656 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
645 nexus->ConfigurePolymorphic(maps, handlers); | 657 nexus->ConfigurePolymorphic(maps, handlers); |
| 658 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 659 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 660 nexus->ConfigurePolymorphic(name, maps, handlers); |
| 661 } else if (kind() == Code::STORE_IC) { |
| 662 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
| 663 nexus->ConfigurePolymorphic(maps, handlers); |
646 } else { | 664 } else { |
647 DCHECK(kind() == Code::KEYED_LOAD_IC); | 665 DCHECK(kind() == Code::KEYED_STORE_IC); |
648 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 666 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
649 nexus->ConfigurePolymorphic(name, maps, handlers); | 667 nexus->ConfigurePolymorphic(name, maps, handlers); |
650 } | 668 } |
651 | 669 |
652 vector_set_ = true; | 670 vector_set_ = true; |
653 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 671 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
654 POLYMORPHIC); | 672 POLYMORPHIC); |
655 } | 673 } |
656 | 674 |
657 | 675 |
658 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 676 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
659 // If the object is undefined or null it's illegal to try to get any | 677 // If the object is undefined or null it's illegal to try to get any |
660 // of its properties; throw a TypeError in that case. | 678 // of its properties; throw a TypeError in that case. |
661 if (object->IsUndefined() || object->IsNull()) { | 679 if (object->IsUndefined() || object->IsNull()) { |
662 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); | 680 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); |
663 } | 681 } |
664 | 682 |
665 // Check if the name is trivially convertible to an index and get | 683 // Check if the name is trivially convertible to an index and get |
666 // the element or char if so. | 684 // the element or char if so. |
667 uint32_t index; | 685 uint32_t index; |
668 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 686 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
669 // Rewrite to the generic keyed load stub. | 687 // Rewrite to the generic keyed load stub. |
670 if (FLAG_use_ic) { | 688 if (FLAG_use_ic) { |
671 if (UseVector()) { | 689 DCHECK(UseVector()); |
672 ConfigureVectorState(MEGAMORPHIC); | 690 ConfigureVectorState(MEGAMORPHIC); |
673 } else { | |
674 set_target(*megamorphic_stub()); | |
675 } | |
676 TRACE_IC("LoadIC", name); | 691 TRACE_IC("LoadIC", name); |
677 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 692 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
678 } | 693 } |
679 Handle<Object> result; | 694 Handle<Object> result; |
680 ASSIGN_RETURN_ON_EXCEPTION( | 695 ASSIGN_RETURN_ON_EXCEPTION( |
681 isolate(), result, | 696 isolate(), result, |
682 Runtime::GetElementOrCharAt(isolate(), object, index), Object); | 697 Runtime::GetElementOrCharAt(isolate(), object, index), Object); |
683 return result; | 698 return result; |
684 } | 699 } |
685 | 700 |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1607 ExtraICState state = ComputeExtraICState(language_mode); | 1622 ExtraICState state = ComputeExtraICState(language_mode); |
1608 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); | 1623 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); |
1609 } | 1624 } |
1610 | 1625 |
1611 | 1626 |
1612 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, | 1627 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
1613 JSReceiver::StoreFromKeyed store_mode) { | 1628 JSReceiver::StoreFromKeyed store_mode) { |
1614 if (state() == UNINITIALIZED) { | 1629 if (state() == UNINITIALIZED) { |
1615 // This is the first time we execute this inline cache. Set the target to | 1630 // This is the first time we execute this inline cache. Set the target to |
1616 // the pre monomorphic stub to delay setting the monomorphic state. | 1631 // the pre monomorphic stub to delay setting the monomorphic state. |
1617 set_target(*pre_monomorphic_stub()); | 1632 if (FLAG_vector_stores) { |
| 1633 ConfigureVectorState(PREMONOMORPHIC); |
| 1634 } else { |
| 1635 set_target(*pre_monomorphic_stub()); |
| 1636 } |
1618 TRACE_IC("StoreIC", lookup->name()); | 1637 TRACE_IC("StoreIC", lookup->name()); |
1619 return; | 1638 return; |
1620 } | 1639 } |
1621 | 1640 |
1622 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1641 bool use_ic = LookupForWrite(lookup, value, store_mode); |
1623 if (!use_ic) { | 1642 if (!use_ic) { |
1624 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1643 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
1625 } | 1644 } |
1626 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); | 1645 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); |
1627 | 1646 |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2046 | 2065 |
2047 Handle<Object> store_handle; | 2066 Handle<Object> store_handle; |
2048 Handle<Code> stub = megamorphic_stub(); | 2067 Handle<Code> stub = megamorphic_stub(); |
2049 | 2068 |
2050 if (key->IsInternalizedString() || key->IsSymbol()) { | 2069 if (key->IsInternalizedString() || key->IsSymbol()) { |
2051 ASSIGN_RETURN_ON_EXCEPTION( | 2070 ASSIGN_RETURN_ON_EXCEPTION( |
2052 isolate(), store_handle, | 2071 isolate(), store_handle, |
2053 StoreIC::Store(object, Handle<Name>::cast(key), value, | 2072 StoreIC::Store(object, Handle<Name>::cast(key), value, |
2054 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 2073 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
2055 Object); | 2074 Object); |
2056 if (!is_target_set()) { | 2075 if (FLAG_vector_stores) { |
2057 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2076 if (!is_vector_set()) { |
2058 "unhandled internalized string key"); | 2077 ConfigureVectorState(MEGAMORPHIC); |
2059 TRACE_IC("StoreIC", key); | 2078 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
2060 set_target(*stub); | 2079 "unhandled internalized string key"); |
| 2080 TRACE_IC("StoreIC", key); |
| 2081 } |
| 2082 } else { |
| 2083 if (!is_target_set()) { |
| 2084 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2085 "unhandled internalized string key"); |
| 2086 TRACE_IC("StoreIC", key); |
| 2087 set_target(*stub); |
| 2088 } |
2061 } | 2089 } |
2062 return store_handle; | 2090 return store_handle; |
2063 } | 2091 } |
2064 | 2092 |
2065 bool use_ic = | 2093 bool use_ic = |
2066 FLAG_use_ic && !object->IsStringWrapper() && | 2094 FLAG_use_ic && !object->IsStringWrapper() && |
2067 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && | 2095 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && |
2068 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); | 2096 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); |
2069 if (use_ic && !object->IsSmi()) { | 2097 if (use_ic && !object->IsSmi()) { |
2070 // Don't use ICs for maps of the objects in Array's prototype chain. We | 2098 // Don't use ICs for maps of the objects in Array's prototype chain. We |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2107 } | 2135 } |
2108 | 2136 |
2109 if (store_handle.is_null()) { | 2137 if (store_handle.is_null()) { |
2110 ASSIGN_RETURN_ON_EXCEPTION( | 2138 ASSIGN_RETURN_ON_EXCEPTION( |
2111 isolate(), store_handle, | 2139 isolate(), store_handle, |
2112 Runtime::SetObjectProperty(isolate(), object, key, value, | 2140 Runtime::SetObjectProperty(isolate(), object, key, value, |
2113 language_mode()), | 2141 language_mode()), |
2114 Object); | 2142 Object); |
2115 } | 2143 } |
2116 | 2144 |
2117 DCHECK(!is_target_set()); | 2145 if (FLAG_vector_stores) { |
2118 Code* megamorphic = *megamorphic_stub(); | 2146 if (!is_vector_set() || stub.is_null()) { |
2119 if (*stub == megamorphic) { | 2147 Code* megamorphic = *megamorphic_stub(); |
2120 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 2148 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { |
2121 } | 2149 ConfigureVectorState(MEGAMORPHIC); |
2122 if (*stub == *slow_stub()) { | 2150 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
2123 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); | 2151 *stub == megamorphic ? "set generic" : "slow stub"); |
2124 } | 2152 } |
2125 DCHECK(!stub.is_null()); | 2153 } |
2126 if (!AddressIsDeoptimizedCode()) { | 2154 } else { |
2127 set_target(*stub); | 2155 DCHECK(!is_target_set()); |
| 2156 Code* megamorphic = *megamorphic_stub(); |
| 2157 if (*stub == megamorphic) { |
| 2158 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
| 2159 } else if (*stub == *slow_stub()) { |
| 2160 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); |
| 2161 } |
| 2162 |
| 2163 DCHECK(!stub.is_null()); |
| 2164 if (!AddressIsDeoptimizedCode()) { |
| 2165 set_target(*stub); |
| 2166 } |
2128 } | 2167 } |
2129 TRACE_IC("StoreIC", key); | 2168 TRACE_IC("StoreIC", key); |
2130 | 2169 |
2131 return store_handle; | 2170 return store_handle; |
2132 } | 2171 } |
2133 | 2172 |
2134 | 2173 |
2135 bool CallIC::DoCustomHandler(Handle<Object> function, | 2174 bool CallIC::DoCustomHandler(Handle<Object> function, |
2136 const CallICState& callic_state) { | 2175 const CallICState& callic_state) { |
2137 DCHECK(FLAG_use_ic && function->IsJSFunction()); | 2176 DCHECK(FLAG_use_ic && function->IsJSFunction()); |
(...skipping 28 matching lines...) Expand all Loading... |
2166 } | 2205 } |
2167 return false; | 2206 return false; |
2168 } | 2207 } |
2169 | 2208 |
2170 | 2209 |
2171 void CallIC::PatchMegamorphic(Handle<Object> function) { | 2210 void CallIC::PatchMegamorphic(Handle<Object> function) { |
2172 CallICState callic_state(target()->extra_ic_state()); | 2211 CallICState callic_state(target()->extra_ic_state()); |
2173 | 2212 |
2174 // We are going generic. | 2213 // We are going generic. |
2175 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 2214 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
2176 nexus->ConfigureGeneric(); | 2215 nexus->ConfigureMegamorphic(); |
2177 | 2216 |
2178 // Vector-based ICs have a different calling convention in optimized code | 2217 // Vector-based ICs have a different calling convention in optimized code |
2179 // than full code so the correct stub has to be chosen. | 2218 // than full code so the correct stub has to be chosen. |
2180 if (AddressIsOptimizedCode()) { | 2219 if (AddressIsOptimizedCode()) { |
2181 CallICStub stub(isolate(), callic_state); | 2220 CallICStub stub(isolate(), callic_state); |
2182 set_target(*stub.GetCode()); | 2221 set_target(*stub.GetCode()); |
2183 } else { | 2222 } else { |
2184 CallICTrampolineStub stub(isolate(), callic_state); | 2223 CallICTrampolineStub stub(isolate(), callic_state); |
2185 set_target(*stub.GetCode()); | 2224 set_target(*stub.GetCode()); |
2186 } | 2225 } |
(...skipping 14 matching lines...) Expand all Loading... |
2201 CallICState callic_state(target()->extra_ic_state()); | 2240 CallICState callic_state(target()->extra_ic_state()); |
2202 Handle<Object> name = isolate()->factory()->empty_string(); | 2241 Handle<Object> name = isolate()->factory()->empty_string(); |
2203 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 2242 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
2204 Object* feedback = nexus->GetFeedback(); | 2243 Object* feedback = nexus->GetFeedback(); |
2205 | 2244 |
2206 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. | 2245 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. |
2207 DCHECK(!feedback->IsSmi()); | 2246 DCHECK(!feedback->IsSmi()); |
2208 | 2247 |
2209 if (feedback->IsWeakCell() || !function->IsJSFunction()) { | 2248 if (feedback->IsWeakCell() || !function->IsJSFunction()) { |
2210 // We are going generic. | 2249 // We are going generic. |
2211 nexus->ConfigureGeneric(); | 2250 nexus->ConfigureMegamorphic(); |
2212 } else { | 2251 } else { |
2213 // The feedback is either uninitialized or an allocation site. | 2252 // The feedback is either uninitialized or an allocation site. |
2214 // It might be an allocation site because if we re-compile the full code | 2253 // It might be an allocation site because if we re-compile the full code |
2215 // to add deoptimization support, we call with the default call-ic, and | 2254 // to add deoptimization support, we call with the default call-ic, and |
2216 // merely need to patch the target to match the feedback. | 2255 // merely need to patch the target to match the feedback. |
2217 // TODO(mvstanton): the better approach is to dispense with patching | 2256 // TODO(mvstanton): the better approach is to dispense with patching |
2218 // altogether, which is in progress. | 2257 // altogether, which is in progress. |
2219 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || | 2258 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || |
2220 feedback->IsAllocationSite()); | 2259 feedback->IsAllocationSite()); |
2221 | 2260 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2345 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2384 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2346 | 2385 |
2347 return *result; | 2386 return *result; |
2348 } | 2387 } |
2349 | 2388 |
2350 | 2389 |
2351 // Used from ic-<arch>.cc. | 2390 // Used from ic-<arch>.cc. |
2352 RUNTIME_FUNCTION(StoreIC_Miss) { | 2391 RUNTIME_FUNCTION(StoreIC_Miss) { |
2353 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2392 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2354 HandleScope scope(isolate); | 2393 HandleScope scope(isolate); |
2355 DCHECK(args.length() == 3); | |
2356 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
2357 Handle<Object> receiver = args.at<Object>(0); | 2394 Handle<Object> receiver = args.at<Object>(0); |
2358 Handle<Name> key = args.at<Name>(1); | 2395 Handle<Name> key = args.at<Name>(1); |
2359 ic.UpdateState(receiver, key); | 2396 Handle<Object> value = args.at<Object>(2); |
2360 Handle<Object> result; | 2397 Handle<Object> result; |
2361 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2398 |
2362 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | 2399 if (FLAG_vector_stores) { |
| 2400 DCHECK(args.length() == 5); |
| 2401 Handle<Smi> slot = args.at<Smi>(3); |
| 2402 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2403 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2404 if (vector->GetKind(vector_slot) == Code::STORE_IC) { |
| 2405 StoreICNexus nexus(vector, vector_slot); |
| 2406 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2407 ic.UpdateState(receiver, key); |
| 2408 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2409 ic.Store(receiver, key, value)); |
| 2410 } else { |
| 2411 DCHECK(vector->GetKind(vector_slot) == Code::KEYED_STORE_IC); |
| 2412 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2413 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2414 ic.UpdateState(receiver, key); |
| 2415 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2416 ic.Store(receiver, key, value)); |
| 2417 } |
| 2418 } else { |
| 2419 DCHECK(args.length() == 3); |
| 2420 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2421 ic.UpdateState(receiver, key); |
| 2422 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2423 ic.Store(receiver, key, value)); |
| 2424 } |
2363 return *result; | 2425 return *result; |
2364 } | 2426 } |
2365 | 2427 |
2366 | 2428 |
2367 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { | 2429 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { |
2368 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2430 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2369 HandleScope scope(isolate); | 2431 HandleScope scope(isolate); |
2370 DCHECK(args.length() == 3 || args.length() == 4); | |
2371 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
2372 Handle<Object> receiver = args.at<Object>(0); | 2432 Handle<Object> receiver = args.at<Object>(0); |
2373 Handle<Name> key = args.at<Name>(1); | 2433 Handle<Name> key = args.at<Name>(1); |
2374 ic.UpdateState(receiver, key); | 2434 Handle<Object> value = args.at<Object>(2); |
2375 Handle<Object> result; | 2435 Handle<Object> result; |
2376 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2436 |
2377 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | 2437 if (FLAG_vector_stores) { |
| 2438 DCHECK(args.length() == 5); |
| 2439 Handle<Smi> slot = args.at<Smi>(3); |
| 2440 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2441 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2442 if (vector->GetKind(vector_slot) == Code::STORE_IC) { |
| 2443 StoreICNexus nexus(vector, vector_slot); |
| 2444 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2445 ic.UpdateState(receiver, key); |
| 2446 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2447 ic.Store(receiver, key, value)); |
| 2448 } else { |
| 2449 DCHECK(vector->GetKind(vector_slot) == Code::KEYED_STORE_IC); |
| 2450 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2451 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2452 ic.UpdateState(receiver, key); |
| 2453 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2454 ic.Store(receiver, key, value)); |
| 2455 } |
| 2456 } else { |
| 2457 DCHECK(args.length() == 3 || args.length() == 4); |
| 2458 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2459 ic.UpdateState(receiver, key); |
| 2460 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2461 ic.Store(receiver, key, value)); |
| 2462 } |
2378 return *result; | 2463 return *result; |
2379 } | 2464 } |
2380 | 2465 |
2381 | 2466 |
2382 // Used from ic-<arch>.cc. | 2467 // Used from ic-<arch>.cc. |
2383 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { | 2468 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { |
2384 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2469 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2385 HandleScope scope(isolate); | 2470 HandleScope scope(isolate); |
2386 DCHECK(args.length() == 3); | |
2387 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
2388 Handle<Object> receiver = args.at<Object>(0); | 2471 Handle<Object> receiver = args.at<Object>(0); |
2389 Handle<Object> key = args.at<Object>(1); | 2472 Handle<Object> key = args.at<Object>(1); |
2390 ic.UpdateState(receiver, key); | 2473 Handle<Object> value = args.at<Object>(2); |
2391 Handle<Object> result; | 2474 Handle<Object> result; |
2392 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2475 |
2393 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | 2476 if (FLAG_vector_stores) { |
| 2477 DCHECK(args.length() == 5); |
| 2478 Handle<Smi> slot = args.at<Smi>(3); |
| 2479 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2480 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2481 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2482 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2483 ic.UpdateState(receiver, key); |
| 2484 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2485 ic.Store(receiver, key, value)); |
| 2486 } else { |
| 2487 DCHECK(args.length() == 3); |
| 2488 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2489 ic.UpdateState(receiver, key); |
| 2490 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2491 ic.Store(receiver, key, value)); |
| 2492 } |
2394 return *result; | 2493 return *result; |
2395 } | 2494 } |
2396 | 2495 |
2397 | 2496 |
2398 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) { | 2497 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) { |
2399 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2498 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2400 HandleScope scope(isolate); | 2499 HandleScope scope(isolate); |
2401 DCHECK(args.length() == 3); | |
2402 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
2403 Handle<Object> receiver = args.at<Object>(0); | 2500 Handle<Object> receiver = args.at<Object>(0); |
2404 Handle<Object> key = args.at<Object>(1); | 2501 Handle<Object> key = args.at<Object>(1); |
2405 ic.UpdateState(receiver, key); | 2502 Handle<Object> value = args.at<Object>(2); |
2406 Handle<Object> result; | 2503 Handle<Object> result; |
2407 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2504 |
2408 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | 2505 if (FLAG_vector_stores) { |
| 2506 DCHECK(args.length() == 5); |
| 2507 Handle<Smi> slot = args.at<Smi>(3); |
| 2508 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2509 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2510 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2511 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2512 ic.UpdateState(receiver, key); |
| 2513 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2514 ic.Store(receiver, key, value)); |
| 2515 } else { |
| 2516 DCHECK(args.length() == 3); |
| 2517 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2518 ic.UpdateState(receiver, key); |
| 2519 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2520 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); |
| 2521 } |
2409 return *result; | 2522 return *result; |
2410 } | 2523 } |
2411 | 2524 |
2412 | 2525 |
2413 RUNTIME_FUNCTION(StoreIC_Slow) { | 2526 RUNTIME_FUNCTION(StoreIC_Slow) { |
2414 HandleScope scope(isolate); | 2527 HandleScope scope(isolate); |
2415 DCHECK(args.length() == 3); | 2528 DCHECK(args.length() == 3); |
2416 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2529 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2417 Handle<Object> object = args.at<Object>(0); | 2530 Handle<Object> object = args.at<Object>(0); |
2418 Handle<Object> key = args.at<Object>(1); | 2531 Handle<Object> key = args.at<Object>(1); |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2938 static const Address IC_utilities[] = { | 3051 static const Address IC_utilities[] = { |
2939 #define ADDR(name) FUNCTION_ADDR(name), | 3052 #define ADDR(name) FUNCTION_ADDR(name), |
2940 IC_UTIL_LIST(ADDR) NULL | 3053 IC_UTIL_LIST(ADDR) NULL |
2941 #undef ADDR | 3054 #undef ADDR |
2942 }; | 3055 }; |
2943 | 3056 |
2944 | 3057 |
2945 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3058 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
2946 } // namespace internal | 3059 } // namespace internal |
2947 } // namespace v8 | 3060 } // namespace v8 |
OLD | NEW |