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

Side by Side Diff: src/objects.cc

Issue 2538693002: Revert of [ic] Use validity cells to protect keyed element stores against object's prototype chain… (Closed)
Patch Set: Created 4 years 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
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 6135 matching lines...) Expand 10 before | Expand all | Expand 10 after
6146 object->set_elements(*new_elements); 6146 object->set_elements(*new_elements);
6147 } else { 6147 } else {
6148 object->set_elements(object->map()->GetInitialElements()); 6148 object->set_elements(object->map()->GetInitialElements());
6149 } 6149 }
6150 } 6150 }
6151 6151
6152 6152
6153 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) { 6153 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
6154 if (dictionary->requires_slow_elements()) return; 6154 if (dictionary->requires_slow_elements()) return;
6155 dictionary->set_requires_slow_elements(); 6155 dictionary->set_requires_slow_elements();
6156 // TODO(verwaest): Remove this hack.
6156 if (map()->is_prototype_map()) { 6157 if (map()->is_prototype_map()) {
6157 // If this object is a prototype (the callee will check), invalidate any 6158 TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
6158 // prototype chains involving it.
6159 InvalidatePrototypeChains(map());
6160 } 6159 }
6161 } 6160 }
6162 6161
6163 6162
6164 Handle<SeededNumberDictionary> JSObject::NormalizeElements( 6163 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
6165 Handle<JSObject> object) { 6164 Handle<JSObject> object) {
6166 DCHECK(!object->HasFixedTypedArrayElements()); 6165 DCHECK(!object->HasFixedTypedArrayElements());
6167 Isolate* isolate = object->GetIsolate(); 6166 Isolate* isolate = object->GetIsolate();
6168 bool is_arguments = object->HasSloppyArgumentsElements(); 6167 bool is_arguments = object->HasSloppyArgumentsElements();
6169 { 6168 {
(...skipping 9435 matching lines...) Expand 10 before | Expand all | Expand 10 after
15605 } 15604 }
15606 } else { 15605 } else {
15607 DCHECK(!object->IsAccessCheckNeeded()); 15606 DCHECK(!object->IsAccessCheckNeeded());
15608 } 15607 }
15609 15608
15610 Heap* heap = isolate->heap(); 15609 Heap* heap = isolate->heap();
15611 // Silently ignore the change if value is not a JSObject or null. 15610 // Silently ignore the change if value is not a JSObject or null.
15612 // SpiderMonkey behaves this way. 15611 // SpiderMonkey behaves this way.
15613 if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true); 15612 if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
15614 15613
15614 bool dictionary_elements_in_chain =
15615 object->map()->DictionaryElementsInPrototypeChainOnly();
15616
15615 bool all_extensible = object->map()->is_extensible(); 15617 bool all_extensible = object->map()->is_extensible();
15616 Handle<JSObject> real_receiver = object; 15618 Handle<JSObject> real_receiver = object;
15617 if (from_javascript) { 15619 if (from_javascript) {
15618 // Find the first object in the chain whose prototype object is not 15620 // Find the first object in the chain whose prototype object is not
15619 // hidden. 15621 // hidden.
15620 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype, 15622 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
15621 PrototypeIterator::END_AT_NON_HIDDEN); 15623 PrototypeIterator::END_AT_NON_HIDDEN);
15622 while (!iter.IsAtEnd()) { 15624 while (!iter.IsAtEnd()) {
15623 // Casting to JSObject is fine because hidden prototypes are never 15625 // Casting to JSObject is fine because hidden prototypes are never
15624 // JSProxies. 15626 // JSProxies.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
15670 // Set the new prototype of the object. 15672 // Set the new prototype of the object.
15671 15673
15672 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); 15674 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
15673 15675
15674 PrototypeOptimizationMode mode = 15676 PrototypeOptimizationMode mode =
15675 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 15677 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
15676 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); 15678 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
15677 DCHECK(new_map->prototype() == *value); 15679 DCHECK(new_map->prototype() == *value);
15678 JSObject::MigrateToMap(real_receiver, new_map); 15680 JSObject::MigrateToMap(real_receiver, new_map);
15679 15681
15682 if (from_javascript && !dictionary_elements_in_chain &&
15683 new_map->DictionaryElementsInPrototypeChainOnly()) {
15684 // If the prototype chain didn't previously have element callbacks, then
15685 // KeyedStoreICs need to be cleared to ensure any that involve this
15686 // map go generic.
15687 TypeFeedbackVector::ClearAllKeyedStoreICs(isolate);
15688 }
15689
15680 heap->ClearInstanceofCache(); 15690 heap->ClearInstanceofCache();
15681 DCHECK(size == object->Size()); 15691 DCHECK(size == object->Size());
15682 return Just(true); 15692 return Just(true);
15683 } 15693 }
15684 15694
15685 // static 15695 // static
15686 void JSObject::SetImmutableProto(Handle<JSObject> object) { 15696 void JSObject::SetImmutableProto(Handle<JSObject> object) {
15687 DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS 15697 DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS
15688 Handle<Map> map(object->map()); 15698 Handle<Map> map(object->map());
15689 15699
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after
17366 uint32_t key = NumberToUint32(k); 17376 uint32_t key = NumberToUint32(k);
17367 if (key < limit) { 17377 if (key < limit) {
17368 if (value->IsUndefined(isolate)) { 17378 if (value->IsUndefined(isolate)) {
17369 undefs++; 17379 undefs++;
17370 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 17380 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17371 // Adding an entry with the key beyond smi-range requires 17381 // Adding an entry with the key beyond smi-range requires
17372 // allocation. Bailout. 17382 // allocation. Bailout.
17373 return bailout; 17383 return bailout;
17374 } else { 17384 } else {
17375 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17385 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17376 new_dict, pos, value, details, object); 17386 new_dict, pos, value, details, object->map()->is_prototype_map());
17377 DCHECK(result.is_identical_to(new_dict)); 17387 DCHECK(result.is_identical_to(new_dict));
17378 USE(result); 17388 USE(result);
17379 pos++; 17389 pos++;
17380 } 17390 }
17381 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { 17391 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
17382 // Adding an entry with the key beyond smi-range requires 17392 // Adding an entry with the key beyond smi-range requires
17383 // allocation. Bailout. 17393 // allocation. Bailout.
17384 return bailout; 17394 return bailout;
17385 } else { 17395 } else {
17386 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17396 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17387 new_dict, key, value, details, object); 17397 new_dict, key, value, details, object->map()->is_prototype_map());
17388 DCHECK(result.is_identical_to(new_dict)); 17398 DCHECK(result.is_identical_to(new_dict));
17389 USE(result); 17399 USE(result);
17390 } 17400 }
17391 } 17401 }
17392 17402
17393 uint32_t result = pos; 17403 uint32_t result = pos;
17394 PropertyDetails no_details = PropertyDetails::Empty(); 17404 PropertyDetails no_details = PropertyDetails::Empty();
17395 while (undefs > 0) { 17405 while (undefs > 0) {
17396 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 17406 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17397 // Adding an entry with the key beyond smi-range requires 17407 // Adding an entry with the key beyond smi-range requires
17398 // allocation. Bailout. 17408 // allocation. Bailout.
17399 return bailout; 17409 return bailout;
17400 } 17410 }
17401 HandleScope scope(isolate); 17411 HandleScope scope(isolate);
17402 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17412 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17403 new_dict, pos, isolate->factory()->undefined_value(), no_details, 17413 new_dict, pos, isolate->factory()->undefined_value(), no_details,
17404 object); 17414 object->map()->is_prototype_map());
17405 DCHECK(result.is_identical_to(new_dict)); 17415 DCHECK(result.is_identical_to(new_dict));
17406 USE(result); 17416 USE(result);
17407 pos++; 17417 pos++;
17408 undefs--; 17418 undefs--;
17409 } 17419 }
17410 17420
17411 object->set_elements(*new_dict); 17421 object->set_elements(*new_dict);
17412 17422
17413 AllowHeapAllocation allocate_return_value; 17423 AllowHeapAllocation allocate_return_value;
17414 return isolate->factory()->NewNumberFromUint(result); 17424 return isolate->factory()->NewNumberFromUint(result);
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after
18166 if (!this->IsKey(isolate, k)) continue; 18176 if (!this->IsKey(isolate, k)) continue;
18167 DCHECK(!IsDeleted(i)); 18177 DCHECK(!IsDeleted(i));
18168 PropertyDetails details = this->DetailsAt(i); 18178 PropertyDetails details = this->DetailsAt(i);
18169 if (details.type() == ACCESSOR_CONSTANT) return true; 18179 if (details.type() == ACCESSOR_CONSTANT) return true;
18170 PropertyAttributes attr = details.attributes(); 18180 PropertyAttributes attr = details.attributes();
18171 if (attr & ALL_ATTRIBUTES_MASK) return true; 18181 if (attr & ALL_ATTRIBUTES_MASK) return true;
18172 } 18182 }
18173 return false; 18183 return false;
18174 } 18184 }
18175 18185
18176 void SeededNumberDictionary::UpdateMaxNumberKey( 18186 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key,
18177 uint32_t key, Handle<JSObject> dictionary_holder) { 18187 bool used_as_prototype) {
18178 DisallowHeapAllocation no_allocation; 18188 DisallowHeapAllocation no_allocation;
18179 // If the dictionary requires slow elements an element has already 18189 // If the dictionary requires slow elements an element has already
18180 // been added at a high index. 18190 // been added at a high index.
18181 if (requires_slow_elements()) return; 18191 if (requires_slow_elements()) return;
18182 // Check if this index is high enough that we should require slow 18192 // Check if this index is high enough that we should require slow
18183 // elements. 18193 // elements.
18184 if (key > kRequiresSlowElementsLimit) { 18194 if (key > kRequiresSlowElementsLimit) {
18185 if (!dictionary_holder.is_null()) { 18195 if (used_as_prototype) {
18186 dictionary_holder->RequireSlowElements(this); 18196 // TODO(verwaest): Remove this hack.
18197 TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
18187 } 18198 }
18188 set_requires_slow_elements(); 18199 set_requires_slow_elements();
18189 return; 18200 return;
18190 } 18201 }
18191 // Update max key value. 18202 // Update max key value.
18192 Object* max_index_object = get(kMaxNumberKeyIndex); 18203 Object* max_index_object = get(kMaxNumberKeyIndex);
18193 if (!max_index_object->IsSmi() || max_number_key() < key) { 18204 if (!max_index_object->IsSmi() || max_number_key() < key) {
18194 FixedArray::set(kMaxNumberKeyIndex, 18205 FixedArray::set(kMaxNumberKeyIndex,
18195 Smi::FromInt(key << kRequiresSlowElementsTagSize)); 18206 Smi::FromInt(key << kRequiresSlowElementsTagSize));
18196 } 18207 }
18197 } 18208 }
18198 18209
18210
18199 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( 18211 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
18200 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18212 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18201 Handle<Object> value, PropertyDetails details, 18213 Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
18202 Handle<JSObject> dictionary_holder) { 18214 dictionary->UpdateMaxNumberKey(key, used_as_prototype);
18203 dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18204 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); 18215 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18205 return Add(dictionary, key, value, details); 18216 return Add(dictionary, key, value, details);
18206 } 18217 }
18207 18218
18208 18219
18209 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( 18220 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
18210 Handle<UnseededNumberDictionary> dictionary, 18221 Handle<UnseededNumberDictionary> dictionary,
18211 uint32_t key, 18222 uint32_t key,
18212 Handle<Object> value) { 18223 Handle<Object> value) {
18213 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); 18224 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18214 return Add(dictionary, key, value, PropertyDetails::Empty()); 18225 return Add(dictionary, key, value, PropertyDetails::Empty());
18215 } 18226 }
18216 18227
18217 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey( 18228 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey(
18218 Handle<UnseededNumberDictionary> dictionary, uint32_t key) { 18229 Handle<UnseededNumberDictionary> dictionary, uint32_t key) {
18219 int entry = dictionary->FindEntry(key); 18230 int entry = dictionary->FindEntry(key);
18220 if (entry == kNotFound) return dictionary; 18231 if (entry == kNotFound) return dictionary;
18221 18232
18222 Factory* factory = dictionary->GetIsolate()->factory(); 18233 Factory* factory = dictionary->GetIsolate()->factory();
18223 dictionary->SetEntry(entry, factory->the_hole_value(), 18234 dictionary->SetEntry(entry, factory->the_hole_value(),
18224 factory->the_hole_value()); 18235 factory->the_hole_value());
18225 dictionary->ElementRemoved(); 18236 dictionary->ElementRemoved();
18226 return dictionary->Shrink(dictionary, key); 18237 return dictionary->Shrink(dictionary, key);
18227 } 18238 }
18228 18239
18229 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( 18240 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
18230 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18241 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18231 Handle<Object> value, Handle<JSObject> dictionary_holder) { 18242 Handle<Object> value, bool used_as_prototype) {
18232 dictionary->UpdateMaxNumberKey(key, dictionary_holder); 18243 dictionary->UpdateMaxNumberKey(key, used_as_prototype);
18233 return AtPut(dictionary, key, value); 18244 return AtPut(dictionary, key, value);
18234 } 18245 }
18235 18246
18236 18247
18237 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut( 18248 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
18238 Handle<UnseededNumberDictionary> dictionary, 18249 Handle<UnseededNumberDictionary> dictionary,
18239 uint32_t key, 18250 uint32_t key,
18240 Handle<Object> value) { 18251 Handle<Object> value) {
18241 return AtPut(dictionary, key, value); 18252 return AtPut(dictionary, key, value);
18242 } 18253 }
18243 18254
18255
18244 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( 18256 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
18245 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18257 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18246 Handle<Object> value, PropertyDetails details, 18258 Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
18247 Handle<JSObject> dictionary_holder) {
18248 int entry = dictionary->FindEntry(key); 18259 int entry = dictionary->FindEntry(key);
18249 if (entry == kNotFound) { 18260 if (entry == kNotFound) {
18250 return AddNumberEntry(dictionary, key, value, details, dictionary_holder); 18261 return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
18251 } 18262 }
18252 // Preserve enumeration index. 18263 // Preserve enumeration index.
18253 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); 18264 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
18254 Handle<Object> object_key = 18265 Handle<Object> object_key =
18255 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); 18266 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
18256 dictionary->SetEntry(entry, object_key, value, details); 18267 dictionary->SetEntry(entry, object_key, value, details);
18257 return dictionary; 18268 return dictionary;
18258 } 18269 }
18259 18270
18260 18271
(...skipping 2167 matching lines...) Expand 10 before | Expand all | Expand 10 after
20428 // depend on this. 20439 // depend on this.
20429 return DICTIONARY_ELEMENTS; 20440 return DICTIONARY_ELEMENTS;
20430 } 20441 }
20431 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20442 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20432 return kind; 20443 return kind;
20433 } 20444 }
20434 } 20445 }
20435 20446
20436 } // namespace internal 20447 } // namespace internal
20437 } // namespace v8 20448 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698