| 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/ic/ic.h" | 5 #include "src/ic/ic.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 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 } | 408 } |
| 409 host->set_profiler_ticks(0); | 409 host->set_profiler_ticks(0); |
| 410 isolate->runtime_profiler()->NotifyICChanged(); | 410 isolate->runtime_profiler()->NotifyICChanged(); |
| 411 // TODO(2029): When an optimized function is patched, it would | 411 // TODO(2029): When an optimized function is patched, it would |
| 412 // be nice to propagate the corresponding type information to its | 412 // be nice to propagate the corresponding type information to its |
| 413 // unoptimized version for the benefit of later inlining. | 413 // unoptimized version for the benefit of later inlining. |
| 414 } | 414 } |
| 415 | 415 |
| 416 | 416 |
| 417 // static | 417 // static |
| 418 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host, | 418 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) { |
| 419 TypeFeedbackVector* vector, State old_state, | |
| 420 State new_state) { | |
| 421 if (host->kind() != Code::FUNCTION) return; | 419 if (host->kind() != Code::FUNCTION) return; |
| 422 | 420 |
| 423 if (FLAG_type_info_threshold > 0) { | |
| 424 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. | |
| 425 int generic_delta = 0; // "Generic" here includes megamorphic. | |
| 426 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, | |
| 427 &generic_delta); | |
| 428 vector->change_ic_with_type_info_count(polymorphic_delta); | |
| 429 vector->change_ic_generic_count(generic_delta); | |
| 430 } | |
| 431 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); | 421 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); |
| 432 info->change_own_type_change_checksum(); | 422 info->change_own_type_change_checksum(); |
| 433 host->set_profiler_ticks(0); | 423 host->set_profiler_ticks(0); |
| 434 isolate->runtime_profiler()->NotifyICChanged(); | 424 isolate->runtime_profiler()->NotifyICChanged(); |
| 435 // TODO(2029): When an optimized function is patched, it would | 425 // TODO(2029): When an optimized function is patched, it would |
| 436 // be nice to propagate the corresponding type information to its | 426 // be nice to propagate the corresponding type information to its |
| 437 // unoptimized version for the benefit of later inlining. | 427 // unoptimized version for the benefit of later inlining. |
| 438 } | 428 } |
| 439 | 429 |
| 440 | 430 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 UNREACHABLE(); | 474 UNREACHABLE(); |
| 485 } | 475 } |
| 486 } | 476 } |
| 487 | 477 |
| 488 | 478 |
| 489 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { | 479 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { |
| 490 if (IsCleared(nexus)) return; | 480 if (IsCleared(nexus)) return; |
| 491 // Make sure to also clear the map used in inline fast cases. If we | 481 // Make sure to also clear the map used in inline fast cases. If we |
| 492 // do not clear these maps, cached code can keep objects alive | 482 // do not clear these maps, cached code can keep objects alive |
| 493 // through the embedded maps. | 483 // through the embedded maps. |
| 494 State state = nexus->StateFromFeedback(); | |
| 495 nexus->ConfigurePremonomorphic(); | 484 nexus->ConfigurePremonomorphic(); |
| 496 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 485 OnTypeFeedbackChanged(isolate, host); |
| 497 } | 486 } |
| 498 | 487 |
| 499 | 488 |
| 500 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 489 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { |
| 501 // Determine our state. | 490 // Determine our state. |
| 502 Object* feedback = nexus->vector()->Get(nexus->slot()); | 491 Object* feedback = nexus->vector()->Get(nexus->slot()); |
| 503 State state = nexus->StateFromFeedback(); | 492 State state = nexus->StateFromFeedback(); |
| 504 | 493 |
| 505 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 494 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
| 506 nexus->ConfigureUninitialized(); | 495 nexus->ConfigureUninitialized(); |
| 507 // The change in state must be processed. | 496 // The change in state must be processed. |
| 508 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 497 OnTypeFeedbackChanged(isolate, host); |
| 509 } | 498 } |
| 510 } | 499 } |
| 511 | 500 |
| 512 | 501 |
| 513 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { | 502 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { |
| 514 if (IsCleared(nexus)) return; | 503 if (IsCleared(nexus)) return; |
| 515 State state = nexus->StateFromFeedback(); | |
| 516 nexus->ConfigurePremonomorphic(); | 504 nexus->ConfigurePremonomorphic(); |
| 517 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 505 OnTypeFeedbackChanged(isolate, host); |
| 518 } | 506 } |
| 519 | 507 |
| 520 | 508 |
| 521 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 509 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, |
| 522 Address constant_pool) { | 510 Address constant_pool) { |
| 523 if (IsCleared(target)) return; | 511 if (IsCleared(target)) return; |
| 524 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, | 512 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, |
| 525 target->extra_ic_state()); | 513 target->extra_ic_state()); |
| 526 SetTargetAtAddress(address, code, constant_pool); | 514 SetTargetAtAddress(address, code, constant_pool); |
| 527 } | 515 } |
| 528 | 516 |
| 529 | 517 |
| 530 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { | 518 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) { |
| 531 if (IsCleared(nexus)) return; | 519 if (IsCleared(nexus)) return; |
| 532 State state = nexus->StateFromFeedback(); | |
| 533 nexus->ConfigurePremonomorphic(); | 520 nexus->ConfigurePremonomorphic(); |
| 534 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 521 OnTypeFeedbackChanged(isolate, host); |
| 535 } | 522 } |
| 536 | 523 |
| 537 | 524 |
| 538 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, | 525 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target, |
| 539 Address constant_pool) { | 526 Address constant_pool) { |
| 540 if (IsCleared(target)) return; | 527 if (IsCleared(target)) return; |
| 541 Handle<Code> code = pre_monomorphic_stub( | 528 Handle<Code> code = pre_monomorphic_stub( |
| 542 isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); | 529 isolate, StoreICState::GetLanguageMode(target->extra_ic_state())); |
| 543 SetTargetAtAddress(address, *code, constant_pool); | 530 SetTargetAtAddress(address, *code, constant_pool); |
| 544 } | 531 } |
| 545 | 532 |
| 546 | 533 |
| 547 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, | 534 void KeyedStoreIC::Clear(Isolate* isolate, Code* host, |
| 548 KeyedStoreICNexus* nexus) { | 535 KeyedStoreICNexus* nexus) { |
| 549 if (IsCleared(nexus)) return; | 536 if (IsCleared(nexus)) return; |
| 550 State state = nexus->StateFromFeedback(); | |
| 551 nexus->ConfigurePremonomorphic(); | 537 nexus->ConfigurePremonomorphic(); |
| 552 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 538 OnTypeFeedbackChanged(isolate, host); |
| 553 } | 539 } |
| 554 | 540 |
| 555 | 541 |
| 556 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, | 542 void CompareIC::Clear(Isolate* isolate, Address address, Code* target, |
| 557 Address constant_pool) { | 543 Address constant_pool) { |
| 558 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); | 544 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); |
| 559 CompareICStub stub(target->stub_key(), isolate); | 545 CompareICStub stub(target->stub_key(), isolate); |
| 560 // Only clear CompareICs that can retain objects. | 546 // Only clear CompareICs that can retain objects. |
| 561 if (stub.state() != CompareICState::KNOWN_RECEIVER) return; | 547 if (stub.state() != CompareICState::KNOWN_RECEIVER) return; |
| 562 SetTargetAtAddress(address, | 548 SetTargetAtAddress(address, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 592 DCHECK(UseVector()); | 578 DCHECK(UseVector()); |
| 593 if (new_state == PREMONOMORPHIC) { | 579 if (new_state == PREMONOMORPHIC) { |
| 594 nexus()->ConfigurePremonomorphic(); | 580 nexus()->ConfigurePremonomorphic(); |
| 595 } else if (new_state == MEGAMORPHIC) { | 581 } else if (new_state == MEGAMORPHIC) { |
| 596 nexus()->ConfigureMegamorphic(); | 582 nexus()->ConfigureMegamorphic(); |
| 597 } else { | 583 } else { |
| 598 UNREACHABLE(); | 584 UNREACHABLE(); |
| 599 } | 585 } |
| 600 | 586 |
| 601 vector_set_ = true; | 587 vector_set_ = true; |
| 602 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 588 OnTypeFeedbackChanged(isolate(), get_host()); |
| 603 new_state); | |
| 604 } | 589 } |
| 605 | 590 |
| 606 | 591 |
| 607 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 592 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
| 608 Handle<Code> handler) { | 593 Handle<Code> handler) { |
| 609 DCHECK(UseVector()); | 594 DCHECK(UseVector()); |
| 610 if (kind() == Code::LOAD_IC) { | 595 if (kind() == Code::LOAD_IC) { |
| 611 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 596 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 612 nexus->ConfigureMonomorphic(map, handler); | 597 nexus->ConfigureMonomorphic(map, handler); |
| 613 } else if (kind() == Code::KEYED_LOAD_IC) { | 598 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 614 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 599 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 615 nexus->ConfigureMonomorphic(name, map, handler); | 600 nexus->ConfigureMonomorphic(name, map, handler); |
| 616 } else if (kind() == Code::STORE_IC) { | 601 } else if (kind() == Code::STORE_IC) { |
| 617 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 602 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
| 618 nexus->ConfigureMonomorphic(map, handler); | 603 nexus->ConfigureMonomorphic(map, handler); |
| 619 } else { | 604 } else { |
| 620 DCHECK(kind() == Code::KEYED_STORE_IC); | 605 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 621 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 606 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
| 622 nexus->ConfigureMonomorphic(name, map, handler); | 607 nexus->ConfigureMonomorphic(name, map, handler); |
| 623 } | 608 } |
| 624 | 609 |
| 625 vector_set_ = true; | 610 vector_set_ = true; |
| 626 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 611 OnTypeFeedbackChanged(isolate(), get_host()); |
| 627 MONOMORPHIC); | |
| 628 } | 612 } |
| 629 | 613 |
| 630 | 614 |
| 631 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 615 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
| 632 CodeHandleList* handlers) { | 616 CodeHandleList* handlers) { |
| 633 DCHECK(UseVector()); | 617 DCHECK(UseVector()); |
| 634 if (kind() == Code::LOAD_IC) { | 618 if (kind() == Code::LOAD_IC) { |
| 635 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 619 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 636 nexus->ConfigurePolymorphic(maps, handlers); | 620 nexus->ConfigurePolymorphic(maps, handlers); |
| 637 } else if (kind() == Code::KEYED_LOAD_IC) { | 621 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 638 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 622 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 639 nexus->ConfigurePolymorphic(name, maps, handlers); | 623 nexus->ConfigurePolymorphic(name, maps, handlers); |
| 640 } else if (kind() == Code::STORE_IC) { | 624 } else if (kind() == Code::STORE_IC) { |
| 641 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 625 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
| 642 nexus->ConfigurePolymorphic(maps, handlers); | 626 nexus->ConfigurePolymorphic(maps, handlers); |
| 643 } else { | 627 } else { |
| 644 DCHECK(kind() == Code::KEYED_STORE_IC); | 628 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 645 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 629 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
| 646 nexus->ConfigurePolymorphic(name, maps, handlers); | 630 nexus->ConfigurePolymorphic(name, maps, handlers); |
| 647 } | 631 } |
| 648 | 632 |
| 649 vector_set_ = true; | 633 vector_set_ = true; |
| 650 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 634 OnTypeFeedbackChanged(isolate(), get_host()); |
| 651 POLYMORPHIC); | |
| 652 } | 635 } |
| 653 | 636 |
| 654 | 637 |
| 655 void IC::ConfigureVectorState(MapHandleList* maps, | 638 void IC::ConfigureVectorState(MapHandleList* maps, |
| 656 MapHandleList* transitioned_maps, | 639 MapHandleList* transitioned_maps, |
| 657 CodeHandleList* handlers) { | 640 CodeHandleList* handlers) { |
| 658 DCHECK(UseVector()); | 641 DCHECK(UseVector()); |
| 659 DCHECK(kind() == Code::KEYED_STORE_IC); | 642 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 660 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 643 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
| 661 nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers); | 644 nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers); |
| 662 | 645 |
| 663 vector_set_ = true; | 646 vector_set_ = true; |
| 664 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 647 OnTypeFeedbackChanged(isolate(), get_host()); |
| 665 POLYMORPHIC); | |
| 666 } | 648 } |
| 667 | 649 |
| 668 | 650 |
| 669 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 651 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
| 670 // If the object is undefined or null it's illegal to try to get any | 652 // If the object is undefined or null it's illegal to try to get any |
| 671 // of its properties; throw a TypeError in that case. | 653 // of its properties; throw a TypeError in that case. |
| 672 if (object->IsUndefined() || object->IsNull()) { | 654 if (object->IsUndefined() || object->IsNull()) { |
| 673 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); | 655 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); |
| 674 } | 656 } |
| 675 | 657 |
| (...skipping 1522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2198 } else { | 2180 } else { |
| 2199 nexus->ConfigureMonomorphic(js_function); | 2181 nexus->ConfigureMonomorphic(js_function); |
| 2200 } | 2182 } |
| 2201 } | 2183 } |
| 2202 | 2184 |
| 2203 if (function->IsJSFunction()) { | 2185 if (function->IsJSFunction()) { |
| 2204 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2186 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
| 2205 name = handle(js_function->shared()->name(), isolate()); | 2187 name = handle(js_function->shared()->name(), isolate()); |
| 2206 } | 2188 } |
| 2207 | 2189 |
| 2208 IC::State new_state = nexus->StateFromFeedback(); | 2190 OnTypeFeedbackChanged(isolate(), get_host()); |
| 2209 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); | |
| 2210 TRACE_IC("CallIC", name); | 2191 TRACE_IC("CallIC", name); |
| 2211 } | 2192 } |
| 2212 | 2193 |
| 2213 | 2194 |
| 2214 #undef TRACE_IC | 2195 #undef TRACE_IC |
| 2215 | 2196 |
| 2216 | 2197 |
| 2217 // ---------------------------------------------------------------------------- | 2198 // ---------------------------------------------------------------------------- |
| 2218 // Static IC stub generators. | 2199 // Static IC stub generators. |
| 2219 // | 2200 // |
| (...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2976 KeyedLoadICNexus nexus(vector, vector_slot); | 2957 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2977 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2958 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2978 ic.UpdateState(receiver, key); | 2959 ic.UpdateState(receiver, key); |
| 2979 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2960 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2980 } | 2961 } |
| 2981 | 2962 |
| 2982 return *result; | 2963 return *result; |
| 2983 } | 2964 } |
| 2984 } // namespace internal | 2965 } // namespace internal |
| 2985 } // namespace v8 | 2966 } // namespace v8 |
| OLD | NEW |