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 |