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