OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 6201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6212 return !AccessorInfo::cast(obj)->prohibits_overwriting(); | 6212 return !AccessorInfo::cast(obj)->prohibits_overwriting(); |
6213 } | 6213 } |
6214 if (obj->IsAccessorPair()) { | 6214 if (obj->IsAccessorPair()) { |
6215 return !AccessorPair::cast(obj)->prohibits_overwriting(); | 6215 return !AccessorPair::cast(obj)->prohibits_overwriting(); |
6216 } | 6216 } |
6217 } | 6217 } |
6218 return true; | 6218 return true; |
6219 } | 6219 } |
6220 | 6220 |
6221 | 6221 |
| 6222 bool Map::DictionaryElementsInPrototypeChainOnly() { |
| 6223 Heap* heap = GetHeap(); |
| 6224 |
| 6225 if (IsDictionaryElementsKind(elements_kind())) { |
| 6226 return false; |
| 6227 } |
| 6228 |
| 6229 for (Object* prototype = this->prototype(); |
| 6230 prototype != heap->null_value(); |
| 6231 prototype = prototype->GetPrototype(GetIsolate())) { |
| 6232 if (prototype->IsJSProxy()) { |
| 6233 // Be conservative, don't walk into proxies. |
| 6234 return true; |
| 6235 } |
| 6236 |
| 6237 if (IsDictionaryElementsKind( |
| 6238 JSObject::cast(prototype)->map()->elements_kind())) { |
| 6239 return true; |
| 6240 } |
| 6241 } |
| 6242 |
| 6243 return false; |
| 6244 } |
| 6245 |
| 6246 |
6222 void JSObject::SetElementCallback(Handle<JSObject> object, | 6247 void JSObject::SetElementCallback(Handle<JSObject> object, |
6223 uint32_t index, | 6248 uint32_t index, |
6224 Handle<Object> structure, | 6249 Handle<Object> structure, |
6225 PropertyAttributes attributes) { | 6250 PropertyAttributes attributes) { |
6226 Heap* heap = object->GetHeap(); | 6251 Heap* heap = object->GetHeap(); |
6227 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6252 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
6228 | 6253 |
6229 // Normalize elements to make this operation simple. | 6254 // Normalize elements to make this operation simple. |
| 6255 bool had_dictionary_elements = object->HasDictionaryElements(); |
6230 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6256 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6231 ASSERT(object->HasDictionaryElements() || | 6257 ASSERT(object->HasDictionaryElements() || |
6232 object->HasDictionaryArgumentsElements()); | 6258 object->HasDictionaryArgumentsElements()); |
6233 | 6259 |
6234 // Update the dictionary with the new CALLBACKS property. | 6260 // Update the dictionary with the new CALLBACKS property. |
6235 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6261 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
6236 details); | 6262 details); |
6237 dictionary->set_requires_slow_elements(); | 6263 dictionary->set_requires_slow_elements(); |
6238 | 6264 |
6239 // Update the dictionary backing store on the object. | 6265 // Update the dictionary backing store on the object. |
6240 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { | 6266 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { |
6241 // Also delete any parameter alias. | 6267 // Also delete any parameter alias. |
6242 // | 6268 // |
6243 // TODO(kmillikin): when deleting the last parameter alias we could | 6269 // TODO(kmillikin): when deleting the last parameter alias we could |
6244 // switch to a direct backing store without the parameter map. This | 6270 // switch to a direct backing store without the parameter map. This |
6245 // would allow GC of the context. | 6271 // would allow GC of the context. |
6246 FixedArray* parameter_map = FixedArray::cast(object->elements()); | 6272 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
6247 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { | 6273 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { |
6248 parameter_map->set(index + 2, heap->the_hole_value()); | 6274 parameter_map->set(index + 2, heap->the_hole_value()); |
6249 } | 6275 } |
6250 parameter_map->set(1, *dictionary); | 6276 parameter_map->set(1, *dictionary); |
6251 } else { | 6277 } else { |
6252 object->set_elements(*dictionary); | 6278 object->set_elements(*dictionary); |
| 6279 |
| 6280 if (!had_dictionary_elements) { |
| 6281 // KeyedStoreICs (at least the non-generic ones) need a reset. |
| 6282 heap->ClearAllICsByKind(Code::KEYED_STORE_IC); |
| 6283 } |
6253 } | 6284 } |
6254 } | 6285 } |
6255 | 6286 |
6256 | 6287 |
6257 void JSObject::SetPropertyCallback(Handle<JSObject> object, | 6288 void JSObject::SetPropertyCallback(Handle<JSObject> object, |
6258 Handle<Name> name, | 6289 Handle<Name> name, |
6259 Handle<Object> structure, | 6290 Handle<Object> structure, |
6260 PropertyAttributes attributes) { | 6291 PropertyAttributes attributes) { |
6261 // Normalize object to make this operation simple. | 6292 // Normalize object to make this operation simple. |
6262 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 6293 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
(...skipping 4339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10602 if (--n == 0) { | 10633 if (--n == 0) { |
10603 info->set_target_cell(replace_with); | 10634 info->set_target_cell(replace_with); |
10604 return; | 10635 return; |
10605 } | 10636 } |
10606 } | 10637 } |
10607 UNREACHABLE(); | 10638 UNREACHABLE(); |
10608 } | 10639 } |
10609 | 10640 |
10610 | 10641 |
10611 void Code::ClearInlineCaches() { | 10642 void Code::ClearInlineCaches() { |
| 10643 ClearInlineCaches(NULL); |
| 10644 } |
| 10645 |
| 10646 |
| 10647 void Code::ClearInlineCaches(Code::Kind kind) { |
| 10648 ClearInlineCaches(&kind); |
| 10649 } |
| 10650 |
| 10651 |
| 10652 void Code::ClearInlineCaches(Code::Kind* kind) { |
10612 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | 10653 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
10613 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | | 10654 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
10614 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | | 10655 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | |
10615 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); | 10656 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); |
10616 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10657 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
10617 RelocInfo* info = it.rinfo(); | 10658 RelocInfo* info = it.rinfo(); |
10618 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); | 10659 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); |
10619 if (target->is_inline_cache_stub()) { | 10660 if (target->is_inline_cache_stub()) { |
10620 IC::Clear(this->GetIsolate(), info->pc()); | 10661 if (kind == NULL || *kind == target->kind()) { |
| 10662 IC::Clear(this->GetIsolate(), info->pc()); |
| 10663 } |
10621 } | 10664 } |
10622 } | 10665 } |
10623 } | 10666 } |
10624 | 10667 |
10625 | 10668 |
10626 void Code::ClearTypeFeedbackCells(Heap* heap) { | 10669 void Code::ClearTypeFeedbackCells(Heap* heap) { |
10627 if (kind() != FUNCTION) return; | 10670 if (kind() != FUNCTION) return; |
10628 Object* raw_info = type_feedback_info(); | 10671 Object* raw_info = type_feedback_info(); |
10629 if (raw_info->IsTypeFeedbackInfo()) { | 10672 if (raw_info->IsTypeFeedbackInfo()) { |
10630 TypeFeedbackCells* type_feedback_cells = | 10673 TypeFeedbackCells* type_feedback_cells = |
(...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11783 pt = pt->GetPrototype(isolate)) { | 11826 pt = pt->GetPrototype(isolate)) { |
11784 if (JSReceiver::cast(pt) == *object) { | 11827 if (JSReceiver::cast(pt) == *object) { |
11785 // Cycle detected. | 11828 // Cycle detected. |
11786 Handle<Object> error = isolate->factory()->NewError( | 11829 Handle<Object> error = isolate->factory()->NewError( |
11787 "cyclic_proto", HandleVector<Object>(NULL, 0)); | 11830 "cyclic_proto", HandleVector<Object>(NULL, 0)); |
11788 isolate->Throw(*error); | 11831 isolate->Throw(*error); |
11789 return Handle<Object>(); | 11832 return Handle<Object>(); |
11790 } | 11833 } |
11791 } | 11834 } |
11792 | 11835 |
| 11836 bool dictionary_elements_in_chain = |
| 11837 object->map()->DictionaryElementsInPrototypeChainOnly(); |
11793 Handle<JSObject> real_receiver = object; | 11838 Handle<JSObject> real_receiver = object; |
11794 | 11839 |
11795 if (skip_hidden_prototypes) { | 11840 if (skip_hidden_prototypes) { |
11796 // Find the first object in the chain whose prototype object is not | 11841 // Find the first object in the chain whose prototype object is not |
11797 // hidden and set the new prototype on that object. | 11842 // hidden and set the new prototype on that object. |
11798 Object* current_proto = real_receiver->GetPrototype(); | 11843 Object* current_proto = real_receiver->GetPrototype(); |
11799 while (current_proto->IsJSObject() && | 11844 while (current_proto->IsJSObject() && |
11800 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { | 11845 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
11801 real_receiver = handle(JSObject::cast(current_proto), isolate); | 11846 real_receiver = handle(JSObject::cast(current_proto), isolate); |
11802 current_proto = current_proto->GetPrototype(isolate); | 11847 current_proto = current_proto->GetPrototype(isolate); |
(...skipping 12 matching lines...) Expand all Loading... |
11815 | 11860 |
11816 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); | 11861 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); |
11817 if (new_map.is_null()) { | 11862 if (new_map.is_null()) { |
11818 new_map = Map::Copy(map); | 11863 new_map = Map::Copy(map); |
11819 Map::PutPrototypeTransition(map, value, new_map); | 11864 Map::PutPrototypeTransition(map, value, new_map); |
11820 new_map->set_prototype(*value); | 11865 new_map->set_prototype(*value); |
11821 } | 11866 } |
11822 ASSERT(new_map->prototype() == *value); | 11867 ASSERT(new_map->prototype() == *value); |
11823 real_receiver->set_map(*new_map); | 11868 real_receiver->set_map(*new_map); |
11824 | 11869 |
| 11870 if (!dictionary_elements_in_chain && |
| 11871 new_map->DictionaryElementsInPrototypeChainOnly()) { |
| 11872 // If the prototype chain didn't previously have element callbacks, then |
| 11873 // KeyedStoreICs need to be cleared to ensure any that involve this |
| 11874 // map go generic. |
| 11875 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); |
| 11876 } |
| 11877 |
11825 heap->ClearInstanceofCache(); | 11878 heap->ClearInstanceofCache(); |
11826 ASSERT(size == object->Size()); | 11879 ASSERT(size == object->Size()); |
11827 return value; | 11880 return value; |
11828 } | 11881 } |
11829 | 11882 |
11830 | 11883 |
11831 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 11884 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
11832 uint32_t first_arg, | 11885 uint32_t first_arg, |
11833 uint32_t arg_count, | 11886 uint32_t arg_count, |
11834 EnsureElementsMode mode) { | 11887 EnsureElementsMode mode) { |
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12803 | 12856 |
12804 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 12857 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
12805 ASSERT(!map()->is_observed()); | 12858 ASSERT(!map()->is_observed()); |
12806 ElementsKind from_kind = map()->elements_kind(); | 12859 ElementsKind from_kind = map()->elements_kind(); |
12807 | 12860 |
12808 if (IsFastHoleyElementsKind(from_kind)) { | 12861 if (IsFastHoleyElementsKind(from_kind)) { |
12809 to_kind = GetHoleyElementsKind(to_kind); | 12862 to_kind = GetHoleyElementsKind(to_kind); |
12810 } | 12863 } |
12811 | 12864 |
12812 if (from_kind == to_kind) return this; | 12865 if (from_kind == to_kind) return this; |
12813 | 12866 // Don't update the site if to_kind isn't fast |
12814 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); | 12867 if (IsFastElementsKind(to_kind)) { |
12815 if (maybe_failure->IsFailure()) return maybe_failure; | 12868 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| 12869 if (maybe_failure->IsFailure()) return maybe_failure; |
| 12870 } |
12816 | 12871 |
12817 Isolate* isolate = GetIsolate(); | 12872 Isolate* isolate = GetIsolate(); |
12818 if (elements() == isolate->heap()->empty_fixed_array() || | 12873 if (elements() == isolate->heap()->empty_fixed_array() || |
12819 (IsFastSmiOrObjectElementsKind(from_kind) && | 12874 (IsFastSmiOrObjectElementsKind(from_kind) && |
12820 IsFastSmiOrObjectElementsKind(to_kind)) || | 12875 IsFastSmiOrObjectElementsKind(to_kind)) || |
12821 (from_kind == FAST_DOUBLE_ELEMENTS && | 12876 (from_kind == FAST_DOUBLE_ELEMENTS && |
12822 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 12877 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
12823 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 12878 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
12824 // No change is needed to the elements() buffer, the transition | 12879 // No change is needed to the elements() buffer, the transition |
12825 // only requires a map change. | 12880 // only requires a map change. |
(...skipping 3637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16463 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16518 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16464 static const char* error_messages_[] = { | 16519 static const char* error_messages_[] = { |
16465 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16520 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16466 }; | 16521 }; |
16467 #undef ERROR_MESSAGES_TEXTS | 16522 #undef ERROR_MESSAGES_TEXTS |
16468 return error_messages_[reason]; | 16523 return error_messages_[reason]; |
16469 } | 16524 } |
16470 | 16525 |
16471 | 16526 |
16472 } } // namespace v8::internal | 16527 } } // namespace v8::internal |
OLD | NEW |