| 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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 Address IC::OriginalCodeAddress() const { | 152 Address IC::OriginalCodeAddress() const { |
| 153 HandleScope scope(isolate()); | 153 HandleScope scope(isolate()); |
| 154 // Compute the JavaScript frame for the frame pointer of this IC | 154 // Compute the JavaScript frame for the frame pointer of this IC |
| 155 // structure. We need this to be able to find the function | 155 // structure. We need this to be able to find the function |
| 156 // corresponding to the frame. | 156 // corresponding to the frame. |
| 157 StackFrameIterator it(isolate()); | 157 StackFrameIterator it(isolate()); |
| 158 while (it.frame()->fp() != this->fp()) it.Advance(); | 158 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 159 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); | 159 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); |
| 160 // Find the function on the stack and both the active code for the | 160 // Find the function on the stack and both the active code for the |
| 161 // function and the original code. | 161 // function and the original code. |
| 162 JSFunction* function = JSFunction::cast(frame->function()); | 162 JSFunction* function = frame->function(); |
| 163 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 163 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
| 164 Code* code = shared->code(); | 164 Code* code = shared->code(); |
| 165 ASSERT(Debug::HasDebugInfo(shared)); | 165 ASSERT(Debug::HasDebugInfo(shared)); |
| 166 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 166 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
| 167 ASSERT(original_code->IsCode()); | 167 ASSERT(original_code->IsCode()); |
| 168 // Get the address of the call site in the active code. This is the | 168 // Get the address of the call site in the active code. This is the |
| 169 // place where the call to DebugBreakXXX is and where the IC | 169 // place where the call to DebugBreakXXX is and where the IC |
| 170 // normally would be. | 170 // normally would be. |
| 171 Address addr = Assembler::target_address_from_return_address(pc()); | 171 Address addr = Assembler::target_address_from_return_address(pc()); |
| 172 // Return the address in the original code. This is the place where | 172 // Return the address in the original code. This is the place where |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 target->type() != Code::NORMAL) { | 224 target->type() != Code::NORMAL) { |
| 225 Code* handler = target->FindFirstCode(); | 225 Code* handler = target->FindFirstCode(); |
| 226 index = map->IndexInCodeCache(name, handler); | 226 index = map->IndexInCodeCache(name, handler); |
| 227 if (index >= 0) { | 227 if (index >= 0) { |
| 228 map->RemoveFromCodeCache(String::cast(name), handler, index); | 228 map->RemoveFromCodeCache(String::cast(name), handler, index); |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 return true; | 231 return true; |
| 232 } | 232 } |
| 233 | 233 |
| 234 // The stub is not in the cache. We've ruled out all other kinds of failure |
| 235 // except for proptotype chain changes, a deprecated map, a map that's |
| 236 // different from the one that the stub expects, or a constant global property |
| 237 // that will become mutable. Threat all those situations as prototype failures |
| 238 // (stay monomorphic if possible). |
| 239 |
| 234 // If the IC is shared between multiple receivers (slow dictionary mode), then | 240 // If the IC is shared between multiple receivers (slow dictionary mode), then |
| 235 // the map cannot be deprecated and the stub invalidated. | 241 // the map cannot be deprecated and the stub invalidated. |
| 236 if (cache_holder != OWN_MAP) return false; | 242 if (cache_holder == OWN_MAP) { |
| 243 Map* old_map = target->FindFirstMap(); |
| 244 if (old_map == map) return true; |
| 245 if (old_map != NULL && old_map->is_deprecated()) return true; |
| 246 } |
| 237 | 247 |
| 238 // The stub is not in the cache. We've ruled out all other kinds of failure | 248 if (receiver->IsGlobalObject()) { |
| 239 // except for proptotype chain changes, a deprecated map, or a map that's | 249 if (!name->IsName()) return false; |
| 240 // different from the one that the stub expects. If the map hasn't changed, | 250 Isolate* isolate = target->GetIsolate(); |
| 241 // assume it's a prototype failure. Treat deprecated maps in the same way as | 251 LookupResult lookup(isolate); |
| 242 // prototype failures (stay monomorphic if possible). | 252 GlobalObject* global = GlobalObject::cast(receiver); |
| 243 Map* old_map = target->FindFirstMap(); | 253 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); |
| 244 if (old_map == NULL) return false; | 254 if (!lookup.IsFound()) return false; |
| 245 return old_map == map || old_map->is_deprecated(); | 255 PropertyCell* cell = global->GetPropertyCell(&lookup); |
| 256 return cell->type()->IsConstant(); |
| 257 } |
| 258 |
| 259 return false; |
| 246 } | 260 } |
| 247 | 261 |
| 248 | 262 |
| 249 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { | 263 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { |
| 250 IC::State state = target->ic_state(); | 264 IC::State state = target->ic_state(); |
| 251 | 265 |
| 252 if (state != MONOMORPHIC || !name->IsString()) return state; | 266 if (state != MONOMORPHIC || !name->IsString()) return state; |
| 253 if (receiver->IsUndefined() || receiver->IsNull()) return state; | 267 if (receiver->IsUndefined() || receiver->IsNull()) return state; |
| 254 | 268 |
| 255 Code::Kind kind = target->kind(); | 269 Code::Kind kind = target->kind(); |
| (...skipping 1388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1644 } | 1658 } |
| 1645 | 1659 |
| 1646 // Observed objects are always modified through the runtime. | 1660 // Observed objects are always modified through the runtime. |
| 1647 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1661 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
| 1648 return JSReceiver::SetPropertyOrFail( | 1662 return JSReceiver::SetPropertyOrFail( |
| 1649 receiver, name, value, NONE, strict_mode, store_mode); | 1663 receiver, name, value, NONE, strict_mode, store_mode); |
| 1650 } | 1664 } |
| 1651 | 1665 |
| 1652 // Use specialized code for setting the length of arrays with fast | 1666 // Use specialized code for setting the length of arrays with fast |
| 1653 // properties. Slow properties might indicate redefinition of the length | 1667 // properties. Slow properties might indicate redefinition of the length |
| 1654 // property. | 1668 // property. Note that when redefined using Object.freeze, it's possible |
| 1669 // to have fast properties but a read-only length. |
| 1655 if (FLAG_use_ic && | 1670 if (FLAG_use_ic && |
| 1656 receiver->IsJSArray() && | 1671 receiver->IsJSArray() && |
| 1657 name->Equals(isolate()->heap()->length_string()) && | 1672 name->Equals(isolate()->heap()->length_string()) && |
| 1658 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1673 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1659 receiver->HasFastProperties()) { | 1674 receiver->HasFastProperties() && |
| 1675 !receiver->map()->is_frozen()) { |
| 1660 Handle<Code> stub = | 1676 Handle<Code> stub = |
| 1661 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); | 1677 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); |
| 1662 set_target(*stub); | 1678 set_target(*stub); |
| 1663 TRACE_IC("StoreIC", name, state, *stub); | 1679 TRACE_IC("StoreIC", name, state, *stub); |
| 1664 return JSReceiver::SetPropertyOrFail( | 1680 return JSReceiver::SetPropertyOrFail( |
| 1665 receiver, name, value, NONE, strict_mode, store_mode); | 1681 receiver, name, value, NONE, strict_mode, store_mode); |
| 1666 } | 1682 } |
| 1667 | 1683 |
| 1668 if (receiver->IsJSGlobalProxy()) { | 1684 if (receiver->IsJSGlobalProxy()) { |
| 1669 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | 1685 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1853 : generic_stub(); | 1869 : generic_stub(); |
| 1854 } | 1870 } |
| 1855 | 1871 |
| 1856 // There are several special cases where an IC that is MONOMORPHIC can still | 1872 // There are several special cases where an IC that is MONOMORPHIC can still |
| 1857 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1873 // transition to a different GetNonTransitioningStoreMode IC that handles a |
| 1858 // superset of the original IC. Handle those here if the receiver map hasn't | 1874 // superset of the original IC. Handle those here if the receiver map hasn't |
| 1859 // changed or it has transitioned to a more general kind. | 1875 // changed or it has transitioned to a more general kind. |
| 1860 KeyedAccessStoreMode old_store_mode = | 1876 KeyedAccessStoreMode old_store_mode = |
| 1861 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1877 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
| 1862 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1878 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
| 1863 if (ic_state == MONOMORPHIC && old_store_mode == STANDARD_STORE) { | 1879 if (ic_state == MONOMORPHIC) { |
| 1864 // If the "old" and "new" maps are in the same elements map family, stay | 1880 // If the "old" and "new" maps are in the same elements map family, stay |
| 1865 // MONOMORPHIC and use the map for the most generic ElementsKind. | 1881 // MONOMORPHIC and use the map for the most generic ElementsKind. |
| 1866 Handle<Map> transitioned_receiver_map = receiver_map; | 1882 Handle<Map> transitioned_receiver_map = receiver_map; |
| 1867 if (IsTransitionStoreMode(store_mode)) { | 1883 if (IsTransitionStoreMode(store_mode)) { |
| 1868 transitioned_receiver_map = | 1884 transitioned_receiver_map = |
| 1869 ComputeTransitionedMap(receiver, store_mode); | 1885 ComputeTransitionedMap(receiver, store_mode); |
| 1870 } | 1886 } |
| 1871 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { | 1887 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { |
| 1872 // Element family is the same, use the "worst" case map. | 1888 // Element family is the same, use the "worst" case map. |
| 1873 store_mode = GetNonTransitioningStoreMode(store_mode); | 1889 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1874 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1890 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1875 transitioned_receiver_map, strict_mode, store_mode); | 1891 transitioned_receiver_map, strict_mode, store_mode); |
| 1876 } else if (*previous_receiver_map == receiver->map()) { | 1892 } else if (*previous_receiver_map == receiver->map() && |
| 1877 if (IsGrowStoreMode(store_mode) || | 1893 old_store_mode == STANDARD_STORE && |
| 1878 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1894 (IsGrowStoreMode(store_mode) || |
| 1879 store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1895 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 1880 // A "normal" IC that handles stores can switch to a version that can | 1896 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
| 1881 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1897 // A "normal" IC that handles stores can switch to a version that can |
| 1882 // and still stay MONOMORPHIC. | 1898 // grow at the end of the array, handle OOB accesses or copy COW arrays |
| 1883 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1899 // and still stay MONOMORPHIC. |
| 1884 receiver_map, strict_mode, store_mode); | 1900 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1885 } | 1901 receiver_map, strict_mode, store_mode); |
| 1886 } | 1902 } |
| 1887 } | 1903 } |
| 1888 | 1904 |
| 1889 ASSERT(ic_state != GENERIC); | 1905 ASSERT(ic_state != GENERIC); |
| 1890 | 1906 |
| 1891 bool map_added = | 1907 bool map_added = |
| 1892 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1908 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
| 1893 | 1909 |
| 1894 if (IsTransitionStoreMode(store_mode)) { | 1910 if (IsTransitionStoreMode(store_mode)) { |
| 1895 Handle<Map> transitioned_receiver_map = | 1911 Handle<Map> transitioned_receiver_map = |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3081 #undef ADDR | 3097 #undef ADDR |
| 3082 }; | 3098 }; |
| 3083 | 3099 |
| 3084 | 3100 |
| 3085 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3101 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3086 return IC_utilities[id]; | 3102 return IC_utilities[id]; |
| 3087 } | 3103 } |
| 3088 | 3104 |
| 3089 | 3105 |
| 3090 } } // namespace v8::internal | 3106 } } // namespace v8::internal |
| OLD | NEW |