OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 bool IC::UpdatePolymorphicIC(State state, | 952 bool IC::UpdatePolymorphicIC(State state, |
953 StrictModeFlag strict_mode, | 953 StrictModeFlag strict_mode, |
954 Handle<JSObject> receiver, | 954 Handle<JSObject> receiver, |
955 Handle<String> name, | 955 Handle<String> name, |
956 Handle<Code> code) { | 956 Handle<Code> code) { |
957 if (code->type() == Code::NORMAL) return false; | 957 if (code->type() == Code::NORMAL) return false; |
958 if (target()->ic_state() == MONOMORPHIC && | 958 if (target()->ic_state() == MONOMORPHIC && |
959 target()->type() == Code::NORMAL) { | 959 target()->type() == Code::NORMAL) { |
960 return false; | 960 return false; |
961 } | 961 } |
| 962 |
962 MapHandleList receiver_maps; | 963 MapHandleList receiver_maps; |
963 CodeHandleList handlers; | 964 CodeHandleList handlers; |
964 target()->FindAllMaps(&receiver_maps); | |
965 int number_of_maps = receiver_maps.length(); | |
966 if (number_of_maps == 0 || number_of_maps >= 4) return false; | |
967 | 965 |
968 target()->FindAllCode(&handlers, receiver_maps.length()); | 966 { |
| 967 AssertNoAllocation no_gc; |
| 968 target()->FindAllMaps(&receiver_maps); |
| 969 int number_of_maps = receiver_maps.length(); |
| 970 if (number_of_maps >= 4) return false; |
| 971 |
| 972 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. |
| 973 // In that case, allow the IC to go back monomorphic. |
| 974 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { |
| 975 return false; |
| 976 } |
| 977 target()->FindAllCode(&handlers, receiver_maps.length()); |
| 978 } |
969 | 979 |
970 if (!AddOneReceiverMapIfMissing(&receiver_maps, | 980 if (!AddOneReceiverMapIfMissing(&receiver_maps, |
971 Handle<Map>(receiver->map()))) { | 981 Handle<Map>(receiver->map()))) { |
972 return false; | 982 return false; |
973 } | 983 } |
974 | 984 |
975 handlers.Add(code); | 985 handlers.Add(code); |
976 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 986 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
977 &receiver_maps, &handlers, name); | 987 &receiver_maps, &handlers, name); |
978 set_target(*ic); | 988 set_target(*ic); |
(...skipping 14 matching lines...) Expand all Loading... |
993 void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1003 void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, |
994 Handle<Code> handler, | 1004 Handle<Code> handler, |
995 Handle<String> name) { | 1005 Handle<String> name) { |
996 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1006 if (handler->type() == Code::NORMAL) return set_target(*handler); |
997 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedMonomorphicIC( | 1007 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedMonomorphicIC( |
998 receiver, handler, name); | 1008 receiver, handler, name); |
999 set_target(*ic); | 1009 set_target(*ic); |
1000 } | 1010 } |
1001 | 1011 |
1002 | 1012 |
| 1013 // Since GC may have been invoked, by the time PatchCache is called, |state| is |
| 1014 // not necessarily equal to target()->state(). |
1003 void IC::PatchCache(State state, | 1015 void IC::PatchCache(State state, |
1004 StrictModeFlag strict_mode, | 1016 StrictModeFlag strict_mode, |
1005 Handle<JSObject> receiver, | 1017 Handle<JSObject> receiver, |
1006 Handle<String> name, | 1018 Handle<String> name, |
1007 Handle<Code> code) { | 1019 Handle<Code> code) { |
1008 switch (state) { | 1020 switch (state) { |
1009 case UNINITIALIZED: | 1021 case UNINITIALIZED: |
1010 case PREMONOMORPHIC: | 1022 case PREMONOMORPHIC: |
1011 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1023 case MONOMORPHIC_PROTOTYPE_FAILURE: |
1012 UpdateMonomorphicIC(receiver, code, name); | 1024 UpdateMonomorphicIC(receiver, code, name); |
1013 break; | 1025 break; |
1014 case MONOMORPHIC: | 1026 case MONOMORPHIC: |
1015 // Only move to megamorphic if the target changes. | 1027 // Only move to megamorphic if the target changes. |
1016 if (target() != *code) { | 1028 if (target() != *code) { |
1017 if (target()->is_load_stub()) { | 1029 if (target()->is_load_stub()) { |
1018 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { | 1030 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { |
1019 break; | 1031 break; |
1020 } | 1032 } |
1021 } | 1033 } |
1022 // We are transitioning from monomorphic to megamorphic case. Place the | 1034 if (target()->type() != Code::NORMAL) { |
1023 // stub compiled for the receiver into stub cache. | 1035 // We are transitioning from monomorphic to megamorphic case. Place |
1024 Map* map = target()->FindFirstMap(); | 1036 // the stub compiled for the receiver into stub cache. |
1025 if (map != NULL) { | 1037 Map* map; |
1026 UpdateMegamorphicCache(map, *name, target()); | 1038 Code* handler; |
| 1039 { |
| 1040 AssertNoAllocation no_gc; |
| 1041 map = target()->FindFirstMap(); |
| 1042 if (map != NULL) { |
| 1043 if (target()->is_load_stub()) { |
| 1044 handler = target()->FindFirstCode(); |
| 1045 } else { |
| 1046 handler = target(); |
| 1047 } |
| 1048 } else { |
| 1049 // Avoid compiler warnings. |
| 1050 handler = NULL; |
| 1051 } |
| 1052 } |
| 1053 if (handler != NULL) { |
| 1054 UpdateMegamorphicCache(map, *name, handler); |
| 1055 } |
1027 } | 1056 } |
1028 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1057 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1029 set_target((strict_mode == kStrictMode) | 1058 set_target((strict_mode == kStrictMode) |
1030 ? *megamorphic_stub_strict() | 1059 ? *megamorphic_stub_strict() |
1031 : *megamorphic_stub()); | 1060 : *megamorphic_stub()); |
1032 } | 1061 } |
1033 break; | 1062 break; |
1034 case MEGAMORPHIC: | 1063 case MEGAMORPHIC: |
1035 // Update the stub cache. | 1064 // Update the stub cache. |
1036 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1065 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1037 break; | 1066 break; |
1038 case POLYMORPHIC: | 1067 case POLYMORPHIC: |
1039 if (target()->is_load_stub()) { | 1068 if (target()->is_load_stub()) { |
1040 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { | 1069 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { |
1041 break; | 1070 break; |
1042 } | 1071 } |
1043 MapHandleList receiver_maps; | 1072 MapHandleList receiver_maps; |
1044 CodeHandleList handlers; | 1073 CodeHandleList handlers; |
1045 target()->FindAllMaps(&receiver_maps); | 1074 { |
1046 target()->FindAllCode(&handlers, receiver_maps.length()); | 1075 AssertNoAllocation no_gc; |
| 1076 target()->FindAllMaps(&receiver_maps); |
| 1077 target()->FindAllCode(&handlers, receiver_maps.length()); |
| 1078 } |
1047 for (int i = 0; i < receiver_maps.length(); i++) { | 1079 for (int i = 0; i < receiver_maps.length(); i++) { |
1048 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); | 1080 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); |
1049 } | 1081 } |
1050 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1082 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1051 set_target(*megamorphic_stub()); | 1083 set_target(*megamorphic_stub()); |
1052 } else { | 1084 } else { |
1053 // When trying to patch a polymorphic keyed load/store element stub | 1085 // When trying to patch a polymorphic keyed load/store element stub |
1054 // with anything other than another polymorphic stub, go generic. | 1086 // with anything other than another polymorphic stub, go generic. |
1055 set_target((strict_mode == kStrictMode) | 1087 set_target((strict_mode == kStrictMode) |
1056 ? *generic_stub_strict() | 1088 ? *generic_stub_strict() |
(...skipping 1585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2642 #undef ADDR | 2674 #undef ADDR |
2643 }; | 2675 }; |
2644 | 2676 |
2645 | 2677 |
2646 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2678 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2647 return IC_utilities[id]; | 2679 return IC_utilities[id]; |
2648 } | 2680 } |
2649 | 2681 |
2650 | 2682 |
2651 } } // namespace v8::internal | 2683 } } // namespace v8::internal |
OLD | NEW |