Chromium Code Reviews| 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 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 610 } | 614 } |
| 611 } | 615 } |
| 612 break; | 616 break; |
| 613 default: | 617 default: |
| 614 return false; | 618 return false; |
| 615 } | 619 } |
| 616 return false; | 620 return false; |
| 617 } | 621 } |
| 618 | 622 |
| 619 | 623 |
| 620 MaybeObject* CallICBase::ComputeMonomorphicStub( | 624 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, |
| 621 LookupResult* lookup, | 625 State state, |
| 622 State state, | 626 Code::ExtraICState extra_state, |
| 623 Code::ExtraICState extra_ic_state, | 627 Handle<Object> object, |
| 624 Handle<Object> object, | 628 Handle<String> name) { |
| 625 Handle<String> name) { | |
| 626 int argc = target()->arguments_count(); | 629 int argc = target()->arguments_count(); |
| 627 MaybeObject* maybe_code = NULL; | 630 Handle<JSObject> holder(lookup->holder()); |
| 628 switch (lookup->type()) { | 631 switch (lookup->type()) { |
| 629 case FIELD: { | 632 case FIELD: { |
| 630 int index = lookup->GetFieldIndex(); | 633 int index = lookup->GetFieldIndex(); |
| 631 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, | 634 return isolate()->stub_cache()->ComputeCallField( |
| 632 kind_, | 635 argc, kind_, extra_state, name, object, holder, index); |
| 633 extra_ic_state, | |
| 634 *name, | |
| 635 *object, | |
| 636 lookup->holder(), | |
| 637 index); | |
| 638 break; | |
| 639 } | 636 } |
| 640 case CONSTANT_FUNCTION: { | 637 case CONSTANT_FUNCTION: { |
| 641 // Get the constant function and compute the code stub for this | 638 // Get the constant function and compute the code stub for this |
| 642 // call; used for rewriting to monomorphic state and making sure | 639 // call; used for rewriting to monomorphic state and making sure |
| 643 // that the code stub is in the stub cache. | 640 // that the code stub is in the stub cache. |
| 644 JSFunction* function = lookup->GetConstantFunction(); | 641 Handle<JSFunction> function(lookup->GetConstantFunction()); |
| 645 maybe_code = | 642 return isolate()->stub_cache()->ComputeCallConstant( |
| 646 isolate()->stub_cache()->ComputeCallConstant(argc, | 643 argc, kind_, extra_state, name, object, holder, function); |
| 647 kind_, | |
| 648 extra_ic_state, | |
| 649 *name, | |
| 650 *object, | |
| 651 lookup->holder(), | |
| 652 function); | |
| 653 break; | |
| 654 } | 644 } |
| 655 case NORMAL: { | 645 case NORMAL: { |
| 656 if (!object->IsJSObject()) return NULL; | 646 // If we return a null handle, the IC will not be patched. |
| 647 if (!object->IsJSObject()) return Handle<Code>::null(); | |
| 657 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 648 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 658 | 649 |
| 659 if (lookup->holder()->IsGlobalObject()) { | 650 if (holder->IsGlobalObject()) { |
| 660 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 651 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 661 JSGlobalPropertyCell* cell = | 652 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
| 662 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 653 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); |
| 663 if (!cell->value()->IsJSFunction()) return NULL; | 654 Handle<JSFunction> function(JSFunction::cast(cell->value())); |
| 664 JSFunction* function = JSFunction::cast(cell->value()); | 655 return isolate()->stub_cache()->ComputeCallGlobal( |
| 665 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, | 656 argc, kind_, extra_state, name, receiver, global, cell, function); |
| 666 kind_, | |
| 667 extra_ic_state, | |
| 668 *name, | |
| 669 *receiver, | |
| 670 global, | |
| 671 cell, | |
| 672 function); | |
| 673 } else { | 657 } else { |
| 674 // There is only one shared stub for calling normalized | 658 // There is only one shared stub for calling normalized |
| 675 // properties. It does not traverse the prototype chain, so the | 659 // properties. It does not traverse the prototype chain, so the |
| 676 // property must be found in the receiver for the stub to be | 660 // property must be found in the receiver for the stub to be |
| 677 // applicable. | 661 // applicable. |
| 678 if (lookup->holder() != *receiver) return NULL; | 662 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); |
| 679 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, | 663 return isolate()->stub_cache()->ComputeCallNormal( |
| 680 kind_, | 664 argc, kind_, extra_state); |
| 681 extra_ic_state, | |
| 682 *name, | |
| 683 *receiver); | |
| 684 } | 665 } |
| 685 break; | 666 break; |
| 686 } | 667 } |
| 687 case INTERCEPTOR: { | 668 case INTERCEPTOR: |
| 688 ASSERT(HasInterceptorGetter(lookup->holder())); | 669 ASSERT(HasInterceptorGetter(*holder)); |
| 689 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( | 670 return isolate()->stub_cache()->ComputeCallInterceptor( |
| 690 argc, | 671 argc, kind_, extra_state, name, object, holder); |
| 691 kind_, | |
| 692 extra_ic_state, | |
| 693 *name, | |
| 694 *object, | |
| 695 lookup->holder()); | |
| 696 break; | |
| 697 } | |
| 698 default: | 672 default: |
| 699 maybe_code = NULL; | 673 return Handle<Code>::null(); |
| 700 break; | |
| 701 } | 674 } |
| 702 return maybe_code; | |
| 703 } | 675 } |
| 704 | 676 |
| 705 | 677 |
| 706 void CallICBase::UpdateCaches(LookupResult* lookup, | 678 void CallICBase::UpdateCaches(LookupResult* lookup, |
| 707 State state, | 679 State state, |
| 708 Code::ExtraICState extra_ic_state, | 680 Code::ExtraICState extra_ic_state, |
| 709 Handle<Object> object, | 681 Handle<Object> object, |
| 710 Handle<String> name) { | 682 Handle<String> name) { |
| 711 // Bail out if we didn't find a result. | 683 // Bail out if we didn't find a result. |
| 712 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 684 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 713 | 685 |
| 714 if (lookup->holder() != *object && | 686 if (lookup->holder() != *object && |
| 715 HasNormalObjectsInPrototypeChain( | 687 HasNormalObjectsInPrototypeChain( |
| 716 isolate(), lookup, object->GetPrototype())) { | 688 isolate(), lookup, object->GetPrototype())) { |
| 717 // Suppress optimization for prototype chains with slow properties objects | 689 // Suppress optimization for prototype chains with slow properties objects |
| 718 // in the middle. | 690 // in the middle. |
| 719 return; | 691 return; |
| 720 } | 692 } |
| 721 | 693 |
| 722 // Compute the number of arguments. | 694 // Compute the number of arguments. |
| 723 int argc = target()->arguments_count(); | 695 int argc = target()->arguments_count(); |
| 724 MaybeObject* maybe_code = NULL; | |
| 725 bool had_proto_failure = false; | 696 bool had_proto_failure = false; |
| 697 Handle<Code> code; | |
| 726 if (state == UNINITIALIZED) { | 698 if (state == UNINITIALIZED) { |
| 727 // This is the first time we execute this inline cache. | 699 // This is the first time we execute this inline cache. |
| 728 // Set the target to the pre monomorphic stub to delay | 700 // Set the target to the pre monomorphic stub to delay |
| 729 // setting the monomorphic state. | 701 // setting the monomorphic state. |
| 730 maybe_code = | 702 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
| 731 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, | 703 argc, kind_, extra_ic_state); |
| 732 kind_, | |
| 733 extra_ic_state); | |
| 734 } else if (state == MONOMORPHIC) { | 704 } else if (state == MONOMORPHIC) { |
| 735 if (kind_ == Code::CALL_IC && | 705 if (kind_ == Code::CALL_IC && |
| 736 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 706 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
| 737 maybe_code = ComputeMonomorphicStub(lookup, | 707 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 738 state, | 708 object, name); |
| 739 extra_ic_state, | |
| 740 object, | |
| 741 name); | |
| 742 } else if (kind_ == Code::CALL_IC && | 709 } else if (kind_ == Code::CALL_IC && |
| 743 TryRemoveInvalidPrototypeDependentStub(target(), | 710 TryRemoveInvalidPrototypeDependentStub(target(), |
| 744 *object, | 711 *object, |
| 745 *name)) { | 712 *name)) { |
| 746 had_proto_failure = true; | 713 had_proto_failure = true; |
| 747 maybe_code = ComputeMonomorphicStub(lookup, | 714 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 748 state, | 715 object, name); |
| 749 extra_ic_state, | |
| 750 object, | |
| 751 name); | |
| 752 } else { | 716 } else { |
| 753 maybe_code = | 717 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 754 isolate()->stub_cache()->ComputeCallMegamorphic(argc, | 718 argc, kind_, extra_ic_state); |
| 755 kind_, | |
| 756 extra_ic_state); | |
| 757 } | 719 } |
| 758 } else { | 720 } else { |
| 759 maybe_code = ComputeMonomorphicStub(lookup, | 721 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
| 760 state, | 722 object, name); |
| 761 extra_ic_state, | |
| 762 object, | |
| 763 name); | |
| 764 } | 723 } |
| 765 | 724 |
| 766 // If we're unable to compute the stub (not enough memory left), we | 725 // If there's no appropriate stub we simply avoid updating the caches. |
| 767 // simply avoid updating the caches. | 726 if (code.is_null()) return; |
| 768 Object* code; | |
| 769 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
| 770 | 727 |
| 771 // Patch the call site depending on the state of the cache. | 728 // Patch the call site depending on the state of the cache. |
| 772 if (state == UNINITIALIZED || | 729 if (state == UNINITIALIZED || |
| 773 state == PREMONOMORPHIC || | 730 state == PREMONOMORPHIC || |
| 774 state == MONOMORPHIC || | 731 state == MONOMORPHIC || |
| 775 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 732 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
| 776 set_target(Code::cast(code)); | 733 set_target(*code); |
| 777 } else if (state == MEGAMORPHIC) { | 734 } else if (state == MEGAMORPHIC) { |
| 778 // Cache code holding map should be consistent with | 735 // Cache code holding map should be consistent with |
| 779 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 736 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
| 780 Map* map = JSObject::cast(object->IsJSObject() ? *object : | 737 Handle<JSObject> cache_object = object->IsJSObject() |
| 781 object->GetPrototype())->map(); | 738 ? Handle<JSObject>::cast(object) |
| 782 | 739 : Handle<JSObject>(JSObject::cast(object->GetPrototype())); |
| 783 // Update the stub cache. | 740 // Update the stub cache. |
| 784 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | 741 isolate()->stub_cache()->Set(*name, cache_object->map(), *code); |
| 785 } | 742 } |
| 786 | 743 |
| 787 USE(had_proto_failure); | |
| 788 #ifdef DEBUG | |
| 789 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 744 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; |
| 790 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 745 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
| 791 name, state, target()); | 746 name, state, target()); |
| 792 #endif | |
| 793 } | 747 } |
| 794 | 748 |
| 795 | 749 |
| 796 MaybeObject* KeyedCallIC::LoadFunction(State state, | 750 MaybeObject* KeyedCallIC::LoadFunction(State state, |
| 797 Handle<Object> object, | 751 Handle<Object> object, |
| 798 Handle<Object> key) { | 752 Handle<Object> key) { |
| 799 if (key->IsSymbol()) { | 753 if (key->IsSymbol()) { |
| 800 return CallICBase::LoadFunction(state, | 754 return CallICBase::LoadFunction(state, |
| 801 Code::kNoExtraICState, | 755 Code::kNoExtraICState, |
| 802 object, | 756 object, |
| 803 Handle<String>::cast(key)); | 757 Handle<String>::cast(key)); |
| 804 } | 758 } |
| 805 | 759 |
| 806 if (object->IsUndefined() || object->IsNull()) { | 760 if (object->IsUndefined() || object->IsNull()) { |
| 807 return TypeError("non_object_property_call", object, key); | 761 return TypeError("non_object_property_call", object, key); |
| 808 } | 762 } |
| 809 | 763 |
| 810 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 764 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { |
| 811 int argc = target()->arguments_count(); | 765 int argc = target()->arguments_count(); |
| 812 Handle<Map> map = | 766 Handle<Map> map = |
| 813 isolate()->factory()->non_strict_arguments_elements_map(); | 767 isolate()->factory()->non_strict_arguments_elements_map(); |
| 814 if (object->IsJSObject() && | 768 if (object->IsJSObject() && |
| 815 Handle<JSObject>::cast(object)->elements()->map() == *map) { | 769 Handle<JSObject>::cast(object)->elements()->map() == *map) { |
| 816 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( | 770 Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments( |
| 817 argc, Code::KEYED_CALL_IC); | 771 argc, Code::KEYED_CALL_IC); |
| 818 Code* code = NULL; | 772 set_target(*code); |
| 819 if (maybe_code->To(&code)) { | 773 TRACE_IC("KeyedCallIC", key, state, target()); |
| 820 set_target(code); | |
| 821 #ifdef DEBUG | |
| 822 TraceIC("KeyedCallIC", key, state, target()); | |
| 823 #endif | |
| 824 } | |
| 825 } else if (!object->IsAccessCheckNeeded()) { | 774 } else if (!object->IsAccessCheckNeeded()) { |
| 826 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 775 Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 827 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 776 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 828 Code* code; | 777 set_target(*code); |
| 829 if (maybe_code->To(&code)) { | 778 TRACE_IC("KeyedCallIC", key, state, target()); |
| 830 set_target(code); | |
| 831 #ifdef DEBUG | |
| 832 TraceIC("KeyedCallIC", key, state, target()); | |
| 833 #endif | |
| 834 } | |
| 835 } | 779 } |
| 836 } | 780 } |
| 837 | 781 |
| 838 Handle<Object> result = GetProperty(object, key); | 782 Handle<Object> result = GetProperty(object, key); |
| 839 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 783 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 840 | 784 |
| 841 // Make receiver an object if the callee requires it. Strict mode or builtin | 785 // Make receiver an object if the callee requires it. Strict mode or builtin |
| 842 // functions do not wrap the receiver, non-strict functions and objects | 786 // functions do not wrap the receiver, non-strict functions and objects |
| 843 // called as functions do. | 787 // called as functions do. |
| 844 ReceiverToObjectIfRequired(result, object); | 788 ReceiverToObjectIfRequired(result, object); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1055 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 999 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
| 1056 set_target(*code); | 1000 set_target(*code); |
| 1057 } else if (state == MONOMORPHIC) { | 1001 } else if (state == MONOMORPHIC) { |
| 1058 set_target(*megamorphic_stub()); | 1002 set_target(*megamorphic_stub()); |
| 1059 } else if (state == MEGAMORPHIC) { | 1003 } else if (state == MEGAMORPHIC) { |
| 1060 // Cache code holding map should be consistent with | 1004 // Cache code holding map should be consistent with |
| 1061 // GenerateMonomorphicCacheProbe. | 1005 // GenerateMonomorphicCacheProbe. |
| 1062 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1006 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
| 1063 } | 1007 } |
| 1064 | 1008 |
| 1065 #ifdef DEBUG | 1009 TRACE_IC("LoadIC", name, state, target()); |
| 1066 TraceIC("LoadIC", name, state, target()); | |
| 1067 #endif | |
| 1068 } | 1010 } |
| 1069 | 1011 |
| 1070 | 1012 |
| 1071 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( | 1013 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( |
| 1072 bool is_js_array, | 1014 bool is_js_array, |
| 1073 ElementsKind elements_kind) { | 1015 ElementsKind elements_kind) { |
| 1074 return KeyedLoadElementStub(elements_kind).TryGetCode(); | 1016 return KeyedLoadElementStub(elements_kind).TryGetCode(); |
| 1075 } | 1017 } |
| 1076 | 1018 |
| 1077 | 1019 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1131 if (object->IsString() && | 1073 if (object->IsString() && |
| 1132 name->Equals(isolate()->heap()->length_symbol())) { | 1074 name->Equals(isolate()->heap()->length_symbol())) { |
| 1133 Handle<String> string = Handle<String>::cast(object); | 1075 Handle<String> string = Handle<String>::cast(object); |
| 1134 Object* code = NULL; | 1076 Object* code = NULL; |
| 1135 { MaybeObject* maybe_code = | 1077 { MaybeObject* maybe_code = |
| 1136 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, | 1078 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, |
| 1137 *string); | 1079 *string); |
| 1138 if (!maybe_code->ToObject(&code)) return maybe_code; | 1080 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 1139 } | 1081 } |
| 1140 set_target(Code::cast(code)); | 1082 set_target(Code::cast(code)); |
| 1141 #ifdef DEBUG | 1083 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1142 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1143 #endif // DEBUG | |
| 1144 return Smi::FromInt(string->length()); | 1084 return Smi::FromInt(string->length()); |
| 1145 } | 1085 } |
| 1146 | 1086 |
| 1147 // Use specialized code for getting the length of arrays. | 1087 // Use specialized code for getting the length of arrays. |
| 1148 if (object->IsJSArray() && | 1088 if (object->IsJSArray() && |
| 1149 name->Equals(isolate()->heap()->length_symbol())) { | 1089 name->Equals(isolate()->heap()->length_symbol())) { |
| 1150 Handle<JSArray> array = Handle<JSArray>::cast(object); | 1090 Handle<JSArray> array = Handle<JSArray>::cast(object); |
| 1151 Object* code; | 1091 Object* code; |
| 1152 { MaybeObject* maybe_code = | 1092 { MaybeObject* maybe_code = |
| 1153 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, | 1093 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, |
| 1154 *array); | 1094 *array); |
| 1155 if (!maybe_code->ToObject(&code)) return maybe_code; | 1095 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 1156 } | 1096 } |
| 1157 set_target(Code::cast(code)); | 1097 set_target(Code::cast(code)); |
| 1158 #ifdef DEBUG | 1098 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1159 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1160 #endif // DEBUG | |
| 1161 return JSArray::cast(*object)->length(); | 1099 return JSArray::cast(*object)->length(); |
| 1162 } | 1100 } |
| 1163 | 1101 |
| 1164 // Use specialized code for getting prototype of functions. | 1102 // Use specialized code for getting prototype of functions. |
| 1165 if (object->IsJSFunction() && | 1103 if (object->IsJSFunction() && |
| 1166 name->Equals(isolate()->heap()->prototype_symbol()) && | 1104 name->Equals(isolate()->heap()->prototype_symbol()) && |
| 1167 JSFunction::cast(*object)->should_have_prototype()) { | 1105 JSFunction::cast(*object)->should_have_prototype()) { |
| 1168 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 1106 Handle<JSFunction> function = Handle<JSFunction>::cast(object); |
| 1169 Object* code; | 1107 Object* code; |
| 1170 { MaybeObject* maybe_code = | 1108 { MaybeObject* maybe_code = |
| 1171 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( | 1109 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( |
| 1172 *name, *function); | 1110 *name, *function); |
| 1173 if (!maybe_code->ToObject(&code)) return maybe_code; | 1111 if (!maybe_code->ToObject(&code)) return maybe_code; |
| 1174 } | 1112 } |
| 1175 set_target(Code::cast(code)); | 1113 set_target(Code::cast(code)); |
| 1176 #ifdef DEBUG | 1114 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1177 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1178 #endif // DEBUG | |
| 1179 return Accessors::FunctionGetPrototype(*object, 0); | 1115 return Accessors::FunctionGetPrototype(*object, 0); |
| 1180 } | 1116 } |
| 1181 } | 1117 } |
| 1182 | 1118 |
| 1183 // Check if the name is trivially convertible to an index and get | 1119 // Check if the name is trivially convertible to an index and get |
| 1184 // the element or char if so. | 1120 // the element or char if so. |
| 1185 uint32_t index = 0; | 1121 uint32_t index = 0; |
| 1186 if (name->AsArrayIndex(&index)) { | 1122 if (name->AsArrayIndex(&index)) { |
| 1187 HandleScope scope(isolate()); | 1123 HandleScope scope(isolate()); |
| 1188 // Rewrite to the generic keyed load stub. | 1124 // Rewrite to the generic keyed load stub. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1247 kNonStrictMode, | 1183 kNonStrictMode, |
| 1248 stub); | 1184 stub); |
| 1249 stub = maybe_stub->IsFailure() ? | 1185 stub = maybe_stub->IsFailure() ? |
| 1250 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1186 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
| 1251 } | 1187 } |
| 1252 } | 1188 } |
| 1253 } | 1189 } |
| 1254 if (stub != NULL) set_target(stub); | 1190 if (stub != NULL) set_target(stub); |
| 1255 } | 1191 } |
| 1256 | 1192 |
| 1257 #ifdef DEBUG | 1193 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1258 TraceIC("KeyedLoadIC", key, state, target()); | |
| 1259 #endif // DEBUG | |
| 1260 | 1194 |
| 1261 // Get the property. | 1195 // Get the property. |
| 1262 return Runtime::GetObjectProperty(isolate(), object, key); | 1196 return Runtime::GetObjectProperty(isolate(), object, key); |
| 1263 } | 1197 } |
| 1264 | 1198 |
| 1265 | 1199 |
| 1266 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 1200 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, |
| 1267 Handle<Object> object, Handle<String> name) { | 1201 Handle<Object> object, Handle<String> name) { |
| 1268 // Bail out if we didn't find a result. | 1202 // Bail out if we didn't find a result. |
| 1269 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 1203 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1326 | 1260 |
| 1327 // Patch the call site depending on the state of the cache. Make | 1261 // Patch the call site depending on the state of the cache. Make |
| 1328 // sure to always rewrite from monomorphic to megamorphic. | 1262 // sure to always rewrite from monomorphic to megamorphic. |
| 1329 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1263 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
| 1330 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1264 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
| 1331 set_target(Code::cast(code)); | 1265 set_target(Code::cast(code)); |
| 1332 } else if (state == MONOMORPHIC) { | 1266 } else if (state == MONOMORPHIC) { |
| 1333 set_target(megamorphic_stub()); | 1267 set_target(megamorphic_stub()); |
| 1334 } | 1268 } |
| 1335 | 1269 |
| 1336 #ifdef DEBUG | 1270 TRACE_IC("KeyedLoadIC", name, state, target()); |
| 1337 TraceIC("KeyedLoadIC", name, state, target()); | |
| 1338 #endif | |
| 1339 } | 1271 } |
| 1340 | 1272 |
| 1341 | 1273 |
| 1342 static bool StoreICableLookup(LookupResult* lookup) { | 1274 static bool StoreICableLookup(LookupResult* lookup) { |
| 1343 // Bail out if we didn't find a result. | 1275 // Bail out if we didn't find a result. |
| 1344 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; | 1276 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; |
| 1345 | 1277 |
| 1346 // If the property is read-only, we leave the IC in its current | 1278 // If the property is read-only, we leave the IC in its current |
| 1347 // state. | 1279 // state. |
| 1348 if (lookup->IsReadOnly()) return false; | 1280 if (lookup->IsReadOnly()) return false; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1443 | 1375 |
| 1444 if (receiver->IsJSGlobalProxy()) { | 1376 if (receiver->IsJSGlobalProxy()) { |
| 1445 // TODO(ulan): find out why we patch this site even with --no-use-ic | 1377 // TODO(ulan): find out why we patch this site even with --no-use-ic |
| 1446 // Generate a generic stub that goes to the runtime when we see a global | 1378 // Generate a generic stub that goes to the runtime when we see a global |
| 1447 // proxy as receiver. | 1379 // proxy as receiver. |
| 1448 Handle<Code> stub = (strict_mode == kStrictMode) | 1380 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1449 ? global_proxy_stub_strict() | 1381 ? global_proxy_stub_strict() |
| 1450 : global_proxy_stub(); | 1382 : global_proxy_stub(); |
| 1451 if (target() != *stub) { | 1383 if (target() != *stub) { |
| 1452 set_target(*stub); | 1384 set_target(*stub); |
| 1453 #ifdef DEBUG | 1385 TRACE_IC("StoreIC", name, state, target()); |
| 1454 TraceIC("StoreIC", name, state, target()); | |
| 1455 #endif | |
| 1456 } | 1386 } |
| 1457 } | 1387 } |
| 1458 | 1388 |
| 1459 // Set the property. | 1389 // Set the property. |
| 1460 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1390 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
| 1461 } | 1391 } |
| 1462 | 1392 |
| 1463 | 1393 |
| 1464 void StoreIC::UpdateCaches(LookupResult* lookup, | 1394 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1465 State state, | 1395 State state, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1539 if (target() != *code) { | 1469 if (target() != *code) { |
| 1540 set_target((strict_mode == kStrictMode) | 1470 set_target((strict_mode == kStrictMode) |
| 1541 ? megamorphic_stub_strict() | 1471 ? megamorphic_stub_strict() |
| 1542 : megamorphic_stub()); | 1472 : megamorphic_stub()); |
| 1543 } | 1473 } |
| 1544 } else if (state == MEGAMORPHIC) { | 1474 } else if (state == MEGAMORPHIC) { |
| 1545 // Update the stub cache. | 1475 // Update the stub cache. |
| 1546 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1476 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
| 1547 } | 1477 } |
| 1548 | 1478 |
| 1549 #ifdef DEBUG | 1479 TRACE_IC("StoreIC", name, state, target()); |
| 1550 TraceIC("StoreIC", name, state, target()); | |
| 1551 #endif | |
| 1552 } | 1480 } |
| 1553 | 1481 |
| 1554 | 1482 |
| 1555 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, | 1483 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, |
| 1556 Map* new_receiver_map) { | 1484 Map* new_receiver_map) { |
| 1557 for (int current = 0; current < receiver_maps->length(); ++current) { | 1485 for (int current = 0; current < receiver_maps->length(); ++current) { |
| 1558 if (receiver_maps->at(current) == new_receiver_map) { | 1486 if (receiver_maps->at(current) == new_receiver_map) { |
| 1559 return false; | 1487 return false; |
| 1560 } | 1488 } |
| 1561 } | 1489 } |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1879 strict_mode, | 1807 strict_mode, |
| 1880 stub); | 1808 stub); |
| 1881 stub = maybe_stub->IsFailure() ? | 1809 stub = maybe_stub->IsFailure() ? |
| 1882 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1810 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
| 1883 } | 1811 } |
| 1884 } | 1812 } |
| 1885 } | 1813 } |
| 1886 if (stub != NULL) set_target(stub); | 1814 if (stub != NULL) set_target(stub); |
| 1887 } | 1815 } |
| 1888 | 1816 |
| 1889 #ifdef DEBUG | 1817 TRACE_IC("KeyedStoreIC", key, state, target()); |
| 1890 TraceIC("KeyedStoreIC", key, state, target()); | |
| 1891 #endif | |
| 1892 | 1818 |
| 1893 // Set the property. | 1819 // Set the property. |
| 1894 return Runtime::SetObjectProperty( | 1820 return Runtime::SetObjectProperty( |
| 1895 isolate(), object , key, value, NONE, strict_mode); | 1821 isolate(), object , key, value, NONE, strict_mode); |
| 1896 } | 1822 } |
| 1897 | 1823 |
| 1898 | 1824 |
| 1899 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1825 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
| 1900 State state, | 1826 State state, |
| 1901 StrictModeFlag strict_mode, | 1827 StrictModeFlag strict_mode, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1959 // sure to always rewrite from monomorphic to megamorphic. | 1885 // sure to always rewrite from monomorphic to megamorphic. |
| 1960 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1886 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
| 1961 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1887 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
| 1962 set_target(Code::cast(code)); | 1888 set_target(Code::cast(code)); |
| 1963 } else if (state == MONOMORPHIC) { | 1889 } else if (state == MONOMORPHIC) { |
| 1964 set_target((strict_mode == kStrictMode) | 1890 set_target((strict_mode == kStrictMode) |
| 1965 ? megamorphic_stub_strict() | 1891 ? megamorphic_stub_strict() |
| 1966 : megamorphic_stub()); | 1892 : megamorphic_stub()); |
| 1967 } | 1893 } |
| 1968 | 1894 |
| 1969 #ifdef DEBUG | 1895 TRACE_IC("KeyedStoreIC", name, state, target()); |
| 1970 TraceIC("KeyedStoreIC", name, state, target()); | |
| 1971 #endif | |
| 1972 } | 1896 } |
| 1973 | 1897 |
|
Vyacheslav Egorov (Chromium)
2011/10/20 10:12:23
add empty line
Kevin Millikin (Chromium)
2011/10/20 10:57:08
Done.
| |
| 1898 #undef TRACE_IC | |
| 1899 | |
| 1974 | 1900 |
| 1975 // ---------------------------------------------------------------------------- | 1901 // ---------------------------------------------------------------------------- |
| 1976 // Static IC stub generators. | 1902 // Static IC stub generators. |
| 1977 // | 1903 // |
| 1978 | 1904 |
| 1979 // Used from ic-<arch>.cc. | 1905 // Used from ic-<arch>.cc. |
| 1980 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 1906 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
| 1981 HandleScope scope(isolate); | 1907 HandleScope scope(isolate); |
| 1982 ASSERT(args.length() == 2); | 1908 ASSERT(args.length() == 2); |
| 1983 CallIC ic(isolate); | 1909 CallIC ic(isolate); |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2586 #undef ADDR | 2512 #undef ADDR |
| 2587 }; | 2513 }; |
| 2588 | 2514 |
| 2589 | 2515 |
| 2590 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2516 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2591 return IC_utilities[id]; | 2517 return IC_utilities[id]; |
| 2592 } | 2518 } |
| 2593 | 2519 |
| 2594 | 2520 |
| 2595 } } // namespace v8::internal | 2521 } } // namespace v8::internal |
| OLD | NEW |