Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(485)

Side by Side Diff: src/objects.cc

Issue 35413006: Correct handling of arrays with callbacks in the prototype chain. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: ports. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 6212 matching lines...) Expand 10 before | Expand all | Expand 10 after
6223 return !AccessorInfo::cast(obj)->prohibits_overwriting(); 6223 return !AccessorInfo::cast(obj)->prohibits_overwriting();
6224 } 6224 }
6225 if (obj->IsAccessorPair()) { 6225 if (obj->IsAccessorPair()) {
6226 return !AccessorPair::cast(obj)->prohibits_overwriting(); 6226 return !AccessorPair::cast(obj)->prohibits_overwriting();
6227 } 6227 }
6228 } 6228 }
6229 return true; 6229 return true;
6230 } 6230 }
6231 6231
6232 6232
6233 bool Map::DictionaryElementsInPrototypeChain() {
6234 Heap* heap = GetHeap();
6235
6236 if (IsDictionaryElementsKind(elements_kind())) {
6237 return true;
6238 }
6239
6240 for (Object* prototype = this->prototype();
6241 prototype != heap->null_value();
6242 prototype = prototype->GetPrototype(GetIsolate())) {
6243 if (prototype->IsJSProxy()) {
6244 // Be conservative, don't walk into proxies.
6245 return true;
6246 }
6247
6248 if (IsDictionaryElementsKind(
6249 JSObject::cast(prototype)->map()->elements_kind())) {
6250 return true;
6251 }
6252 }
6253
6254 return false;
6255 }
6256
6233 void JSObject::SetElementCallback(Handle<JSObject> object, 6257 void JSObject::SetElementCallback(Handle<JSObject> object,
6234 uint32_t index, 6258 uint32_t index,
6235 Handle<Object> structure, 6259 Handle<Object> structure,
6236 PropertyAttributes attributes) { 6260 PropertyAttributes attributes) {
6237 Heap* heap = object->GetHeap(); 6261 Heap* heap = object->GetHeap();
6238 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); 6262 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6239 6263
6240 // Normalize elements to make this operation simple. 6264 // Normalize elements to make this operation simple.
6241 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); 6265 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6242 ASSERT(object->HasDictionaryElements() || 6266 ASSERT(object->HasDictionaryElements() ||
(...skipping 4327 matching lines...) Expand 10 before | Expand all | Expand 10 after
10570 if (--n == 0) { 10594 if (--n == 0) {
10571 info->set_target_cell(replace_with); 10595 info->set_target_cell(replace_with);
10572 return; 10596 return;
10573 } 10597 }
10574 } 10598 }
10575 UNREACHABLE(); 10599 UNREACHABLE();
10576 } 10600 }
10577 10601
10578 10602
10579 void Code::ClearInlineCaches() { 10603 void Code::ClearInlineCaches() {
10604 ClearInlineCaches(NULL);
10605 }
10606
10607
10608 void Code::ClearInlineCaches(Code::Kind kind) {
10609 ClearInlineCaches(&kind);
10610 }
10611
10612
10613 void Code::ClearInlineCaches(Code::Kind* kind) {
10580 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | 10614 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10581 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | 10615 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10582 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | 10616 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
10583 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); 10617 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
10584 for (RelocIterator it(this, mask); !it.done(); it.next()) { 10618 for (RelocIterator it(this, mask); !it.done(); it.next()) {
10585 RelocInfo* info = it.rinfo(); 10619 RelocInfo* info = it.rinfo();
10586 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); 10620 Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10587 if (target->is_inline_cache_stub()) { 10621 if (target->is_inline_cache_stub()) {
10588 IC::Clear(this->GetIsolate(), info->pc()); 10622 if (kind == NULL || *kind == target->kind()) {
10623 IC::Clear(this->GetIsolate(), info->pc());
10624 }
10589 } 10625 }
10590 } 10626 }
10591 } 10627 }
10592 10628
10593 10629
10594 void Code::ClearTypeFeedbackCells(Heap* heap) { 10630 void Code::ClearTypeFeedbackCells(Heap* heap) {
10595 if (kind() != FUNCTION) return; 10631 if (kind() != FUNCTION) return;
10596 Object* raw_info = type_feedback_info(); 10632 Object* raw_info = type_feedback_info();
10597 if (raw_info->IsTypeFeedbackInfo()) { 10633 if (raw_info->IsTypeFeedbackInfo()) {
10598 TypeFeedbackCells* type_feedback_cells = 10634 TypeFeedbackCells* type_feedback_cells =
(...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after
11751 pt = pt->GetPrototype(isolate)) { 11787 pt = pt->GetPrototype(isolate)) {
11752 if (JSReceiver::cast(pt) == *object) { 11788 if (JSReceiver::cast(pt) == *object) {
11753 // Cycle detected. 11789 // Cycle detected.
11754 Handle<Object> error = isolate->factory()->NewError( 11790 Handle<Object> error = isolate->factory()->NewError(
11755 "cyclic_proto", HandleVector<Object>(NULL, 0)); 11791 "cyclic_proto", HandleVector<Object>(NULL, 0));
11756 isolate->Throw(*error); 11792 isolate->Throw(*error);
11757 return Handle<Object>(); 11793 return Handle<Object>();
11758 } 11794 }
11759 } 11795 }
11760 11796
11797 bool dictionary_elements_in_chain =
11798 object->map()->DictionaryElementsInPrototypeChain();
11761 Handle<JSObject> real_receiver = object; 11799 Handle<JSObject> real_receiver = object;
11762 11800
11763 if (skip_hidden_prototypes) { 11801 if (skip_hidden_prototypes) {
11764 // Find the first object in the chain whose prototype object is not 11802 // Find the first object in the chain whose prototype object is not
11765 // hidden and set the new prototype on that object. 11803 // hidden and set the new prototype on that object.
11766 Object* current_proto = real_receiver->GetPrototype(); 11804 Object* current_proto = real_receiver->GetPrototype();
11767 while (current_proto->IsJSObject() && 11805 while (current_proto->IsJSObject() &&
11768 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 11806 JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
11769 real_receiver = handle(JSObject::cast(current_proto), isolate); 11807 real_receiver = handle(JSObject::cast(current_proto), isolate);
11770 current_proto = current_proto->GetPrototype(isolate); 11808 current_proto = current_proto->GetPrototype(isolate);
(...skipping 12 matching lines...) Expand all
11783 11821
11784 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); 11822 Handle<Map> new_map = Map::GetPrototypeTransition(map, value);
11785 if (new_map.is_null()) { 11823 if (new_map.is_null()) {
11786 new_map = Map::Copy(map); 11824 new_map = Map::Copy(map);
11787 Map::PutPrototypeTransition(map, value, new_map); 11825 Map::PutPrototypeTransition(map, value, new_map);
11788 new_map->set_prototype(*value); 11826 new_map->set_prototype(*value);
11789 } 11827 }
11790 ASSERT(new_map->prototype() == *value); 11828 ASSERT(new_map->prototype() == *value);
11791 real_receiver->set_map(*new_map); 11829 real_receiver->set_map(*new_map);
11792 11830
11831 if (!dictionary_elements_in_chain &&
11832 new_map->DictionaryElementsInPrototypeChain()) {
11833 // If the prototype chain didn't previously have element callbacks, then
11834 // KeyedStoreICs need to be cleared to ensure any that involve this
11835 // map go generic.
11836 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11837 }
11838
11793 heap->ClearInstanceofCache(); 11839 heap->ClearInstanceofCache();
11794 ASSERT(size == object->Size()); 11840 ASSERT(size == object->Size());
11795 return value; 11841 return value;
11796 } 11842 }
11797 11843
11798 11844
11799 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, 11845 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
11800 uint32_t first_arg, 11846 uint32_t first_arg,
11801 uint32_t arg_count, 11847 uint32_t arg_count,
11802 EnsureElementsMode mode) { 11848 EnsureElementsMode mode) {
(...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after
12771 12817
12772 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 12818 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
12773 ASSERT(!map()->is_observed()); 12819 ASSERT(!map()->is_observed());
12774 ElementsKind from_kind = map()->elements_kind(); 12820 ElementsKind from_kind = map()->elements_kind();
12775 12821
12776 if (IsFastHoleyElementsKind(from_kind)) { 12822 if (IsFastHoleyElementsKind(from_kind)) {
12777 to_kind = GetHoleyElementsKind(to_kind); 12823 to_kind = GetHoleyElementsKind(to_kind);
12778 } 12824 }
12779 12825
12780 if (from_kind == to_kind) return this; 12826 if (from_kind == to_kind) return this;
12781 12827 // Don't update the site if to_kind isn't fast
12782 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); 12828 if (IsFastElementsKind(to_kind)) {
12783 if (maybe_failure->IsFailure()) return maybe_failure; 12829 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
12830 if (maybe_failure->IsFailure()) return maybe_failure;
12831 }
12784 12832
12785 Isolate* isolate = GetIsolate(); 12833 Isolate* isolate = GetIsolate();
12786 if (elements() == isolate->heap()->empty_fixed_array() || 12834 if (elements() == isolate->heap()->empty_fixed_array() ||
12787 (IsFastSmiOrObjectElementsKind(from_kind) && 12835 (IsFastSmiOrObjectElementsKind(from_kind) &&
12788 IsFastSmiOrObjectElementsKind(to_kind)) || 12836 IsFastSmiOrObjectElementsKind(to_kind)) ||
12789 (from_kind == FAST_DOUBLE_ELEMENTS && 12837 (from_kind == FAST_DOUBLE_ELEMENTS &&
12790 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { 12838 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12791 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); 12839 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12792 // No change is needed to the elements() buffer, the transition 12840 // No change is needed to the elements() buffer, the transition
12793 // only requires a map change. 12841 // only requires a map change.
(...skipping 3602 matching lines...) Expand 10 before | Expand all | Expand 10 after
16396 #define ERROR_MESSAGES_TEXTS(C, T) T, 16444 #define ERROR_MESSAGES_TEXTS(C, T) T,
16397 static const char* error_messages_[] = { 16445 static const char* error_messages_[] = {
16398 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16446 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16399 }; 16447 };
16400 #undef ERROR_MESSAGES_TEXTS 16448 #undef ERROR_MESSAGES_TEXTS
16401 return error_messages_[reason]; 16449 return error_messages_[reason];
16402 } 16450 }
16403 16451
16404 16452
16405 } } // namespace v8::internal 16453 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698