| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 } else { | 93 } else { |
| 94 PrintF("<unknown>"); | 94 PrintF("<unknown>"); |
| 95 } | 95 } |
| 96 PrintF(" (%c->%c)", | 96 PrintF(" (%c->%c)", |
| 97 TransitionMarkFromState(old_state), | 97 TransitionMarkFromState(old_state), |
| 98 TransitionMarkFromState(new_state)); | 98 TransitionMarkFromState(new_state)); |
| 99 name->Print(); | 99 name->Print(); |
| 100 PrintF("]\n"); | 100 PrintF("]\n"); |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 #endif | 103 #endif // DEBUG |
| 104 |
| 105 |
| 106 #define TRACE_IC(type, name, old_state, new_target) \ |
| 107 ASSERT((TraceIC(type, name, old_state, new_target), true)) |
| 104 | 108 |
| 105 | 109 |
| 106 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 110 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
| 107 ASSERT(isolate == Isolate::Current()); | 111 ASSERT(isolate == Isolate::Current()); |
| 108 // To improve the performance of the (much used) IC code, we unfold | 112 // To improve the performance of the (much used) IC code, we unfold |
| 109 // a few levels of the stack frame iteration code. This yields a | 113 // a few levels of the stack frame iteration code. This yields a |
| 110 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. | 114 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. |
| 111 const Address entry = | 115 const Address entry = |
| 112 Isolate::c_entry_fp(isolate->thread_local_top()); | 116 Isolate::c_entry_fp(isolate->thread_local_top()); |
| 113 Address* pc_address = | 117 Address* pc_address = |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 } | 575 } |
| 572 } | 576 } |
| 573 break; | 577 break; |
| 574 default: | 578 default: |
| 575 return false; | 579 return false; |
| 576 } | 580 } |
| 577 return false; | 581 return false; |
| 578 } | 582 } |
| 579 | 583 |
| 580 | 584 |
| 581 MaybeObject* CallICBase::ComputeMonomorphicStub( | 585 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, |
| 582 LookupResult* lookup, | 586 State state, |
| 583 State state, | 587 Code::ExtraICState extra_state, |
| 584 Code::ExtraICState extra_ic_state, | 588 Handle<Object> object, |
| 585 Handle<Object> object, | 589 Handle<String> name) { |
| 586 Handle<String> name) { | |
| 587 int argc = target()->arguments_count(); | 590 int argc = target()->arguments_count(); |
| 588 MaybeObject* maybe_code = NULL; | 591 Handle<JSObject> holder(lookup->holder()); |
| 589 switch (lookup->type()) { | 592 switch (lookup->type()) { |
| 590 case FIELD: { | 593 case FIELD: { |
| 591 int index = lookup->GetFieldIndex(); | 594 int index = lookup->GetFieldIndex(); |
| 592 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, | 595 return isolate()->stub_cache()->ComputeCallField( |
| 593 kind_, | 596 argc, kind_, extra_state, name, object, holder, index); |
| 594 extra_ic_state, | |
| 595 *name, | |
| 596 *object, | |
| 597 lookup->holder(), | |
| 598 index); | |
| 599 break; | |
| 600 } | 597 } |
| 601 case CONSTANT_FUNCTION: { | 598 case CONSTANT_FUNCTION: { |
| 602 // Get the constant function and compute the code stub for this | 599 // Get the constant function and compute the code stub for this |
| 603 // call; used for rewriting to monomorphic state and making sure | 600 // call; used for rewriting to monomorphic state and making sure |
| 604 // that the code stub is in the stub cache. | 601 // that the code stub is in the stub cache. |
| 605 JSFunction* function = lookup->GetConstantFunction(); | 602 Handle<JSFunction> function(lookup->GetConstantFunction()); |
| 606 maybe_code = | 603 return isolate()->stub_cache()->ComputeCallConstant( |
| 607 isolate()->stub_cache()->ComputeCallConstant(argc, | 604 argc, kind_, extra_state, name, object, holder, function); |
| 608 kind_, | |
| 609 extra_ic_state, | |
| 610 *name, | |
| 611 *object, | |
| 612 lookup->holder(), | |
| 613 function); | |
| 614 break; | |
| 615 } | 605 } |
| 616 case NORMAL: { | 606 case NORMAL: { |
| 617 if (!object->IsJSObject()) return NULL; | 607 // If we return a null handle, the IC will not be patched. |
| 608 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 618 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 609 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 619 | 610 |
| 620 if (lookup->holder()->IsGlobalObject()) { | 611 if (holder->IsGlobalObject()) { |
| 621 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 612 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 622 JSGlobalPropertyCell* cell = | 613 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
| 623 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 614 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); |
| 624 if (!cell->value()->IsJSFunction()) return NULL; | 615 Handle<JSFunction> function(JSFunction::cast(cell->value())); |
| 625 JSFunction* function = JSFunction::cast(cell->value()); | 616 return isolate()->stub_cache()->ComputeCallGlobal( |
| 626 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, | 617 argc, kind_, extra_state, name, receiver, global, cell, function); |
| 627 kind_, | |
| 628 extra_ic_state, | |
| 629 *name, | |
| 630 *receiver, | |
| 631 global, | |
| 632 cell, | |
| 633 function); | |
| 634 } else { | 618 } else { |
| 635 // There is only one shared stub for calling normalized | 619 // There is only one shared stub for calling normalized |
| 636 // properties. It does not traverse the prototype chain, so the | 620 // properties. It does not traverse the prototype chain, so the |
| 637 // property must be found in the receiver for the stub to be | 621 // property must be found in the receiver for the stub to be |
| 638 // applicable. | 622 // applicable. |
| 639 if (lookup->holder() != *receiver) return NULL; | 623 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); |
| 640 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, | 624 return isolate()->stub_cache()->ComputeCallNormal( |
| 641 kind_, | 625 argc, kind_, extra_state); |
| 642 extra_ic_state, | |
| 643 *name, | |
| 644 *receiver); | |
| 645 } | 626 } |
| 646 break; | 627 break; |
| 647 } | 628 } |
| 648 case INTERCEPTOR: { | 629 case INTERCEPTOR: |
| 649 ASSERT(HasInterceptorGetter(lookup->holder())); | 630 ASSERT(HasInterceptorGetter(*holder)); |
| 650 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( | 631 return isolate()->stub_cache()->ComputeCallInterceptor( |
| 651 argc, | 632 argc, kind_, extra_state, name, object, holder); |
| 652 kind_, | |
| 653 extra_ic_state, | |
| 654 *name, | |
| 655 *object, | |
| 656 lookup->holder()); | |
| 657 break; | |
| 658 } | |
| 659 default: | 633 default: |
| 660 maybe_code = NULL; | 634 return Handle<Code>::null(); |
| 661 break; | |
| 662 } | 635 } |
| 663 return maybe_code; | |
| 664 } | 636 } |
| 665 | 637 |
| 666 | 638 |
| 667 void CallICBase::UpdateCaches(LookupResult* lookup, | 639 void CallICBase::UpdateCaches(LookupResult* lookup, |
| 668 State state, | 640 State state, |
| 669 Code::ExtraICState extra_ic_state, | 641 Code::ExtraICState extra_ic_state, |
| 670 Handle<Object> object, | 642 Handle<Object> object, |
| 671 Handle<String> name) { | 643 Handle<String> name) { |
| 672 // Bail out if we didn't find a result. | 644 // Bail out if we didn't find a result. |
| 673 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 645 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 674 | 646 |
| 675 if (lookup->holder() != *object && | 647 if (lookup->holder() != *object && |
| 676 HasNormalObjectsInPrototypeChain( | 648 HasNormalObjectsInPrototypeChain( |
| 677 isolate(), lookup, object->GetPrototype())) { | 649 isolate(), lookup, object->GetPrototype())) { |
| 678 // Suppress optimization for prototype chains with slow properties objects | 650 // Suppress optimization for prototype chains with slow properties objects |
| 679 // in the middle. | 651 // in the middle. |
| 680 return; | 652 return; |
| 681 } | 653 } |
| 682 | 654 |
| 683 // Compute the number of arguments. | 655 // Compute the number of arguments. |
| 684 int argc = target()->arguments_count(); | 656 int argc = target()->arguments_count(); |
| 685 MaybeObject* maybe_code = NULL; | |
| 686 bool had_proto_failure = false; | 657 bool had_proto_failure = false; |
| 658 Handle<Code> code; |
| 687 if (state == UNINITIALIZED) { | 659 if (state == UNINITIALIZED) { |
| 688 // This is the first time we execute this inline cache. | 660 // This is the first time we execute this inline cache. |
| 689 // Set the target to the pre monomorphic stub to delay | 661 // Set the target to the pre monomorphic stub to delay |
| 690 // setting the monomorphic state. | 662 // setting the monomorphic state. |
| 691 maybe_code = | 663 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
| 692 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, | 664 argc, kind_, extra_ic_state); |
| 693 kind_, | |
| 694 extra_ic_state); | |
| 695 } else if (state == MONOMORPHIC) { | 665 } else if (state == MONOMORPHIC) { |
| 696 if (kind_ == Code::CALL_IC && | 666 if (kind_ == Code::CALL_IC && |
| 697 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 667 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
| 698 maybe_code = ComputeMonomorphicStub(lookup, | 668 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 699 state, | 669 object, name); |
| 700 extra_ic_state, | |
| 701 object, | |
| 702 name); | |
| 703 } else if (kind_ == Code::CALL_IC && | 670 } else if (kind_ == Code::CALL_IC && |
| 704 TryRemoveInvalidPrototypeDependentStub(target(), | 671 TryRemoveInvalidPrototypeDependentStub(target(), |
| 705 *object, | 672 *object, |
| 706 *name)) { | 673 *name)) { |
| 707 had_proto_failure = true; | 674 had_proto_failure = true; |
| 708 maybe_code = ComputeMonomorphicStub(lookup, | 675 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 709 state, | 676 object, name); |
| 710 extra_ic_state, | |
| 711 object, | |
| 712 name); | |
| 713 } else { | 677 } else { |
| 714 maybe_code = | 678 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 715 isolate()->stub_cache()->ComputeCallMegamorphic(argc, | 679 argc, kind_, extra_ic_state); |
| 716 kind_, | |
| 717 extra_ic_state); | |
| 718 } | 680 } |
| 719 } else { | 681 } else { |
| 720 maybe_code = ComputeMonomorphicStub(lookup, | 682 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 721 state, | 683 object, name); |
| 722 extra_ic_state, | |
| 723 object, | |
| 724 name); | |
| 725 } | 684 } |
| 726 | 685 |
| 727 // If we're unable to compute the stub (not enough memory left), we | 686 // If there's no appropriate stub we simply avoid updating the caches. |
| 728 // simply avoid updating the caches. | 687 if (code.is_null()) return; |
| 729 Object* code; | |
| 730 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
| 731 | 688 |
| 732 // Patch the call site depending on the state of the cache. | 689 // Patch the call site depending on the state of the cache. |
| 733 if (state == UNINITIALIZED || | 690 if (state == UNINITIALIZED || |
| 734 state == PREMONOMORPHIC || | 691 state == PREMONOMORPHIC || |
| 735 state == MONOMORPHIC || | 692 state == MONOMORPHIC || |
| 736 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 693 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
| 737 set_target(Code::cast(code)); | 694 set_target(*code); |
| 738 } else if (state == MEGAMORPHIC) { | 695 } else if (state == MEGAMORPHIC) { |
| 739 // Cache code holding map should be consistent with | 696 // Cache code holding map should be consistent with |
| 740 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 697 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
| 741 Map* map = JSObject::cast(object->IsJSObject() ? *object : | 698 Handle<JSObject> cache_object = object->IsJSObject() |
| 742 object->GetPrototype())->map(); | 699 ? Handle<JSObject>::cast(object) |
| 743 | 700 : Handle<JSObject>(JSObject::cast(object->GetPrototype())); |
| 744 // Update the stub cache. | 701 // Update the stub cache. |
| 745 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | 702 isolate()->stub_cache()->Set(*name, cache_object->map(), *code); |
| 746 } | 703 } |
| 747 | 704 |
| 748 USE(had_proto_failure); | |
| 749 #ifdef DEBUG | |
| 750 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 705 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; |
| 751 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 706 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
| 752 name, state, target()); | 707 name, state, target()); |
| 753 #endif | |
| 754 } | 708 } |
| 755 | 709 |
| 756 | 710 |
| 757 MaybeObject* KeyedCallIC::LoadFunction(State state, | 711 MaybeObject* KeyedCallIC::LoadFunction(State state, |
| 758 Handle<Object> object, | 712 Handle<Object> object, |
| 759 Handle<Object> key) { | 713 Handle<Object> key) { |
| 760 if (key->IsSymbol()) { | 714 if (key->IsSymbol()) { |
| 761 return CallICBase::LoadFunction(state, | 715 return CallICBase::LoadFunction(state, |
| 762 Code::kNoExtraICState, | 716 Code::kNoExtraICState, |
| 763 object, | 717 object, |
| 764 Handle<String>::cast(key)); | 718 Handle<String>::cast(key)); |
| 765 } | 719 } |
| 766 | 720 |
| 767 if (object->IsUndefined() || object->IsNull()) { | 721 if (object->IsUndefined() || object->IsNull()) { |
| 768 return TypeError("non_object_property_call", object, key); | 722 return TypeError("non_object_property_call", object, key); |
| 769 } | 723 } |
| 770 | 724 |
| 771 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 725 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { |
| 772 int argc = target()->arguments_count(); | 726 int argc = target()->arguments_count(); |
| 773 Handle<Map> map = | 727 Handle<Map> map = |
| 774 isolate()->factory()->non_strict_arguments_elements_map(); | 728 isolate()->factory()->non_strict_arguments_elements_map(); |
| 775 if (object->IsJSObject() && | 729 if (object->IsJSObject() && |
| 776 Handle<JSObject>::cast(object)->elements()->map() == *map) { | 730 Handle<JSObject>::cast(object)->elements()->map() == *map) { |
| 777 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( | 731 Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments( |
| 778 argc, Code::KEYED_CALL_IC); | 732 argc, Code::KEYED_CALL_IC); |
| 779 Code* code = NULL; | 733 set_target(*code); |
| 780 if (maybe_code->To(&code)) { | 734 TRACE_IC("KeyedCallIC", key, state, target()); |
| 781 set_target(code); | |
| 782 #ifdef DEBUG | |
| 783 TraceIC("KeyedCallIC", key, state, target()); | |
| 784 #endif | |
| 785 } | |
| 786 } else if (!object->IsAccessCheckNeeded()) { | 735 } else if (!object->IsAccessCheckNeeded()) { |
| 787 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 736 Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 788 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 737 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 789 Code* code; | 738 set_target(*code); |
| 790 if (maybe_code->To(&code)) { | 739 TRACE_IC("KeyedCallIC", key, state, target()); |
| 791 set_target(code); | |
| 792 #ifdef DEBUG | |
| 793 TraceIC("KeyedCallIC", key, state, target()); | |
| 794 #endif | |
| 795 } | |
| 796 } | 740 } |
| 797 } | 741 } |
| 798 | 742 |
| 799 Handle<Object> result = GetProperty(object, key); | 743 Handle<Object> result = GetProperty(object, key); |
| 800 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 744 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 801 | 745 |
| 802 // Make receiver an object if the callee requires it. Strict mode or builtin | 746 // Make receiver an object if the callee requires it. Strict mode or builtin |
| 803 // functions do not wrap the receiver, non-strict functions and objects | 747 // functions do not wrap the receiver, non-strict functions and objects |
| 804 // called as functions do. | 748 // called as functions do. |
| 805 ReceiverToObjectIfRequired(result, object); | 749 ReceiverToObjectIfRequired(result, object); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 960 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
| 1017 set_target(*code); | 961 set_target(*code); |
| 1018 } else if (state == MONOMORPHIC) { | 962 } else if (state == MONOMORPHIC) { |
| 1019 set_target(*megamorphic_stub()); | 963 set_target(*megamorphic_stub()); |
| 1020 } else if (state == MEGAMORPHIC) { | 964 } else if (state == MEGAMORPHIC) { |
| 1021 // Cache code holding map should be consistent with | 965 // Cache code holding map should be consistent with |
| 1022 // GenerateMonomorphicCacheProbe. | 966 // GenerateMonomorphicCacheProbe. |
| 1023 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 967 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
| 1024 } | 968 } |
| 1025 | 969 |
| 1026 #ifdef DEBUG | 970 TRACE_IC("LoadIC", name, state, target()); |
| 1027 TraceIC("LoadIC", name, state, target()); | |
| 1028 #endif | |
| 1029 } | 971 } |
| 1030 | 972 |
| 1031 | 973 |
| 1032 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( | 974 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( |
| 1033 bool is_js_array, | 975 bool is_js_array, |
| 1034 ElementsKind elements_kind) { | 976 ElementsKind elements_kind) { |
| 1035 return KeyedLoadElementStub(elements_kind).TryGetCode(); | 977 return KeyedLoadElementStub(elements_kind).TryGetCode(); |
| 1036 } | 978 } |
| 1037 | 979 |
| 1038 | 980 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 | 1031 |
| 1090 // Use specialized code for getting the length of strings. | 1032 // Use specialized code for getting the length of strings. |
| 1091 if (object->IsString() && | 1033 if (object->IsString() && |
| 1092 name->Equals(isolate()->heap()->length_symbol())) { | 1034 name->Equals(isolate()->heap()->length_symbol())) { |
| 1093 Handle<String> string = Handle<String>::cast(object); | 1035 Handle<String> string = Handle<String>::cast(object); |
| 1094 Handle<Code> code = | 1036 Handle<Code> code = |
| 1095 isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, | 1037 isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, |
| 1096 string); | 1038 string); |
| 1097 ASSERT(!code.is_null()); | 1039 ASSERT(!code.is_null()); |
| 1098 set_target(*code); | 1040 set_target(*code); |
| 1099 #ifdef DEBUG | 1041 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1100 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1101 #endif // DEBUG | |
| 1102 return Smi::FromInt(string->length()); | 1042 return Smi::FromInt(string->length()); |
| 1103 } | 1043 } |
| 1104 | 1044 |
| 1105 // Use specialized code for getting the length of arrays. | 1045 // Use specialized code for getting the length of arrays. |
| 1106 if (object->IsJSArray() && | 1046 if (object->IsJSArray() && |
| 1107 name->Equals(isolate()->heap()->length_symbol())) { | 1047 name->Equals(isolate()->heap()->length_symbol())) { |
| 1108 Handle<JSArray> array = Handle<JSArray>::cast(object); | 1048 Handle<JSArray> array = Handle<JSArray>::cast(object); |
| 1109 Handle<Code> code = | 1049 Handle<Code> code = |
| 1110 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array); | 1050 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array); |
| 1111 ASSERT(!code.is_null()); | 1051 ASSERT(!code.is_null()); |
| 1112 set_target(*code); | 1052 set_target(*code); |
| 1113 #ifdef DEBUG | 1053 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1114 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1115 #endif // DEBUG | |
| 1116 return array->length(); | 1054 return array->length(); |
| 1117 } | 1055 } |
| 1118 | 1056 |
| 1119 // Use specialized code for getting prototype of functions. | 1057 // Use specialized code for getting prototype of functions. |
| 1120 if (object->IsJSFunction() && | 1058 if (object->IsJSFunction() && |
| 1121 name->Equals(isolate()->heap()->prototype_symbol()) && | 1059 name->Equals(isolate()->heap()->prototype_symbol()) && |
| 1122 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 1060 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
| 1123 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 1061 Handle<JSFunction> function = Handle<JSFunction>::cast(object); |
| 1124 Handle<Code> code = | 1062 Handle<Code> code = |
| 1125 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( | 1063 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( |
| 1126 name, function); | 1064 name, function); |
| 1127 ASSERT(!code.is_null()); | 1065 ASSERT(!code.is_null()); |
| 1128 set_target(*code); | 1066 set_target(*code); |
| 1129 #ifdef DEBUG | 1067 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1130 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1131 #endif // DEBUG | |
| 1132 return Accessors::FunctionGetPrototype(*object, 0); | 1068 return Accessors::FunctionGetPrototype(*object, 0); |
| 1133 } | 1069 } |
| 1134 } | 1070 } |
| 1135 | 1071 |
| 1136 // Check if the name is trivially convertible to an index and get | 1072 // Check if the name is trivially convertible to an index and get |
| 1137 // the element or char if so. | 1073 // the element or char if so. |
| 1138 uint32_t index = 0; | 1074 uint32_t index = 0; |
| 1139 if (name->AsArrayIndex(&index)) { | 1075 if (name->AsArrayIndex(&index)) { |
| 1140 // Rewrite to the generic keyed load stub. | 1076 // Rewrite to the generic keyed load stub. |
| 1141 if (FLAG_use_ic) set_target(*generic_stub()); | 1077 if (FLAG_use_ic) set_target(*generic_stub()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 } else if (receiver->HasIndexedInterceptor()) { | 1127 } else if (receiver->HasIndexedInterceptor()) { |
| 1192 stub = indexed_interceptor_stub(); | 1128 stub = indexed_interceptor_stub(); |
| 1193 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { | 1129 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
| 1194 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); | 1130 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); |
| 1195 } | 1131 } |
| 1196 } | 1132 } |
| 1197 } | 1133 } |
| 1198 if (!stub.is_null()) set_target(*stub); | 1134 if (!stub.is_null()) set_target(*stub); |
| 1199 } | 1135 } |
| 1200 | 1136 |
| 1201 #ifdef DEBUG | 1137 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1202 TraceIC("KeyedLoadIC", key, state, target()); | |
| 1203 #endif // DEBUG | |
| 1204 | 1138 |
| 1205 // Get the property. | 1139 // Get the property. |
| 1206 return Runtime::GetObjectProperty(isolate(), object, key); | 1140 return Runtime::GetObjectProperty(isolate(), object, key); |
| 1207 } | 1141 } |
| 1208 | 1142 |
| 1209 | 1143 |
| 1210 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, | 1144 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, |
| 1211 State state, | 1145 State state, |
| 1212 Handle<Object> object, | 1146 Handle<Object> object, |
| 1213 Handle<String> name) { | 1147 Handle<String> name) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 | 1200 |
| 1267 // Patch the call site depending on the state of the cache. Make | 1201 // Patch the call site depending on the state of the cache. Make |
| 1268 // sure to always rewrite from monomorphic to megamorphic. | 1202 // sure to always rewrite from monomorphic to megamorphic. |
| 1269 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1203 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
| 1270 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1204 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
| 1271 set_target(*code); | 1205 set_target(*code); |
| 1272 } else if (state == MONOMORPHIC) { | 1206 } else if (state == MONOMORPHIC) { |
| 1273 set_target(*megamorphic_stub()); | 1207 set_target(*megamorphic_stub()); |
| 1274 } | 1208 } |
| 1275 | 1209 |
| 1276 #ifdef DEBUG | 1210 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1277 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1278 #endif | |
| 1279 } | 1211 } |
| 1280 | 1212 |
| 1281 | 1213 |
| 1282 static bool StoreICableLookup(LookupResult* lookup) { | 1214 static bool StoreICableLookup(LookupResult* lookup) { |
| 1283 // Bail out if we didn't find a result. | 1215 // Bail out if we didn't find a result. |
| 1284 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; | 1216 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; |
| 1285 | 1217 |
| 1286 // If the property is read-only, we leave the IC in its current | 1218 // If the property is read-only, we leave the IC in its current |
| 1287 // state. | 1219 // state. |
| 1288 if (lookup->IsReadOnly()) return false; | 1220 if (lookup->IsReadOnly()) return false; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1383 | 1315 |
| 1384 if (receiver->IsJSGlobalProxy()) { | 1316 if (receiver->IsJSGlobalProxy()) { |
| 1385 // TODO(ulan): find out why we patch this site even with --no-use-ic | 1317 // TODO(ulan): find out why we patch this site even with --no-use-ic |
| 1386 // Generate a generic stub that goes to the runtime when we see a global | 1318 // Generate a generic stub that goes to the runtime when we see a global |
| 1387 // proxy as receiver. | 1319 // proxy as receiver. |
| 1388 Handle<Code> stub = (strict_mode == kStrictMode) | 1320 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1389 ? global_proxy_stub_strict() | 1321 ? global_proxy_stub_strict() |
| 1390 : global_proxy_stub(); | 1322 : global_proxy_stub(); |
| 1391 if (target() != *stub) { | 1323 if (target() != *stub) { |
| 1392 set_target(*stub); | 1324 set_target(*stub); |
| 1393 #ifdef DEBUG | 1325 TRACE_IC("StoreIC", name, state, target()); |
| 1394 TraceIC("StoreIC", name, state, target()); | |
| 1395 #endif | |
| 1396 } | 1326 } |
| 1397 } | 1327 } |
| 1398 | 1328 |
| 1399 // Set the property. | 1329 // Set the property. |
| 1400 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1330 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
| 1401 } | 1331 } |
| 1402 | 1332 |
| 1403 | 1333 |
| 1404 void StoreIC::UpdateCaches(LookupResult* lookup, | 1334 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1405 State state, | 1335 State state, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 if (target() != *code) { | 1409 if (target() != *code) { |
| 1480 set_target((strict_mode == kStrictMode) | 1410 set_target((strict_mode == kStrictMode) |
| 1481 ? megamorphic_stub_strict() | 1411 ? megamorphic_stub_strict() |
| 1482 : megamorphic_stub()); | 1412 : megamorphic_stub()); |
| 1483 } | 1413 } |
| 1484 } else if (state == MEGAMORPHIC) { | 1414 } else if (state == MEGAMORPHIC) { |
| 1485 // Update the stub cache. | 1415 // Update the stub cache. |
| 1486 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1416 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
| 1487 } | 1417 } |
| 1488 | 1418 |
| 1489 #ifdef DEBUG | 1419 TRACE_IC("StoreIC", name, state, target()); |
| 1490 TraceIC("StoreIC", name, state, target()); | |
| 1491 #endif | |
| 1492 } | 1420 } |
| 1493 | 1421 |
| 1494 | 1422 |
| 1495 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, | 1423 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, |
| 1496 Map* new_receiver_map) { | 1424 Map* new_receiver_map) { |
| 1497 for (int current = 0; current < receiver_maps->length(); ++current) { | 1425 for (int current = 0; current < receiver_maps->length(); ++current) { |
| 1498 if (receiver_maps->at(current) == new_receiver_map) { | 1426 if (receiver_maps->at(current) == new_receiver_map) { |
| 1499 return false; | 1427 return false; |
| 1500 } | 1428 } |
| 1501 } | 1429 } |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 strict_mode, | 1718 strict_mode, |
| 1791 stub); | 1719 stub); |
| 1792 stub = maybe_stub->IsFailure() ? | 1720 stub = maybe_stub->IsFailure() ? |
| 1793 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1721 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
| 1794 } | 1722 } |
| 1795 } | 1723 } |
| 1796 } | 1724 } |
| 1797 if (stub != NULL) set_target(stub); | 1725 if (stub != NULL) set_target(stub); |
| 1798 } | 1726 } |
| 1799 | 1727 |
| 1800 #ifdef DEBUG | 1728 TRACE_IC("KeyedStoreIC", key, state, target()); |
| 1801 TraceIC("KeyedStoreIC", key, state, target()); | |
| 1802 #endif | |
| 1803 | 1729 |
| 1804 // Set the property. | 1730 // Set the property. |
| 1805 return Runtime::SetObjectProperty( | 1731 return Runtime::SetObjectProperty( |
| 1806 isolate(), object , key, value, NONE, strict_mode); | 1732 isolate(), object , key, value, NONE, strict_mode); |
| 1807 } | 1733 } |
| 1808 | 1734 |
| 1809 | 1735 |
| 1810 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1736 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
| 1811 State state, | 1737 State state, |
| 1812 StrictModeFlag strict_mode, | 1738 StrictModeFlag strict_mode, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1870 // sure to always rewrite from monomorphic to megamorphic. | 1796 // sure to always rewrite from monomorphic to megamorphic. |
| 1871 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1797 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
| 1872 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1798 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
| 1873 set_target(Code::cast(code)); | 1799 set_target(Code::cast(code)); |
| 1874 } else if (state == MONOMORPHIC) { | 1800 } else if (state == MONOMORPHIC) { |
| 1875 set_target((strict_mode == kStrictMode) | 1801 set_target((strict_mode == kStrictMode) |
| 1876 ? megamorphic_stub_strict() | 1802 ? megamorphic_stub_strict() |
| 1877 : megamorphic_stub()); | 1803 : megamorphic_stub()); |
| 1878 } | 1804 } |
| 1879 | 1805 |
| 1880 #ifdef DEBUG | 1806 TRACE_IC("KeyedStoreIC", name, state, target()); |
| 1881 TraceIC("KeyedStoreIC", name, state, target()); | |
| 1882 #endif | |
| 1883 } | 1807 } |
| 1884 | 1808 |
| 1885 | 1809 |
| 1810 #undef TRACE_IC |
| 1811 |
| 1812 |
| 1886 // ---------------------------------------------------------------------------- | 1813 // ---------------------------------------------------------------------------- |
| 1887 // Static IC stub generators. | 1814 // Static IC stub generators. |
| 1888 // | 1815 // |
| 1889 | 1816 |
| 1890 // Used from ic-<arch>.cc. | 1817 // Used from ic-<arch>.cc. |
| 1891 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 1818 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
| 1892 HandleScope scope(isolate); | 1819 HandleScope scope(isolate); |
| 1893 ASSERT(args.length() == 2); | 1820 ASSERT(args.length() == 2); |
| 1894 CallIC ic(isolate); | 1821 CallIC ic(isolate); |
| 1895 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1822 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2497 #undef ADDR | 2424 #undef ADDR |
| 2498 }; | 2425 }; |
| 2499 | 2426 |
| 2500 | 2427 |
| 2501 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2428 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2502 return IC_utilities[id]; | 2429 return IC_utilities[id]; |
| 2503 } | 2430 } |
| 2504 | 2431 |
| 2505 | 2432 |
| 2506 } } // namespace v8::internal | 2433 } } // namespace v8::internal |
| OLD | NEW |