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

Side by Side Diff: src/objects.cc

Issue 2534613002: [ic] Use validity cells to protect keyed element stores against object's prototype chain modificati… (Closed)
Patch Set: The fix 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
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 6145 matching lines...) Expand 10 before | Expand all | Expand 10 after
6156 object->set_elements(*new_elements); 6156 object->set_elements(*new_elements);
6157 } else { 6157 } else {
6158 object->set_elements(object->map()->GetInitialElements()); 6158 object->set_elements(object->map()->GetInitialElements());
6159 } 6159 }
6160 } 6160 }
6161 6161
6162 6162
6163 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) { 6163 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
6164 if (dictionary->requires_slow_elements()) return; 6164 if (dictionary->requires_slow_elements()) return;
6165 dictionary->set_requires_slow_elements(); 6165 dictionary->set_requires_slow_elements();
6166 // TODO(verwaest): Remove this hack.
6167 if (map()->is_prototype_map()) { 6166 if (map()->is_prototype_map()) {
6168 TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate()); 6167 // If this object is a prototype (the callee will check), invalidate any
6168 // prototype chains involving it.
6169 InvalidatePrototypeChains(map());
6169 } 6170 }
6170 } 6171 }
6171 6172
6172 6173
6173 Handle<SeededNumberDictionary> JSObject::NormalizeElements( 6174 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
6174 Handle<JSObject> object) { 6175 Handle<JSObject> object) {
6175 DCHECK(!object->HasFixedTypedArrayElements()); 6176 DCHECK(!object->HasFixedTypedArrayElements());
6176 Isolate* isolate = object->GetIsolate(); 6177 Isolate* isolate = object->GetIsolate();
6177 bool is_arguments = object->HasSloppyArgumentsElements(); 6178 bool is_arguments = object->HasSloppyArgumentsElements();
6178 { 6179 {
(...skipping 9406 matching lines...) Expand 10 before | Expand all | Expand 10 after
15585 } 15586 }
15586 } else { 15587 } else {
15587 DCHECK(!object->IsAccessCheckNeeded()); 15588 DCHECK(!object->IsAccessCheckNeeded());
15588 } 15589 }
15589 15590
15590 Heap* heap = isolate->heap(); 15591 Heap* heap = isolate->heap();
15591 // Silently ignore the change if value is not a JSObject or null. 15592 // Silently ignore the change if value is not a JSObject or null.
15592 // SpiderMonkey behaves this way. 15593 // SpiderMonkey behaves this way.
15593 if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true); 15594 if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
15594 15595
15595 bool dictionary_elements_in_chain =
15596 object->map()->DictionaryElementsInPrototypeChainOnly();
15597
15598 bool all_extensible = object->map()->is_extensible(); 15596 bool all_extensible = object->map()->is_extensible();
15599 Handle<JSObject> real_receiver = object; 15597 Handle<JSObject> real_receiver = object;
15600 if (from_javascript) { 15598 if (from_javascript) {
15601 // Find the first object in the chain whose prototype object is not 15599 // Find the first object in the chain whose prototype object is not
15602 // hidden. 15600 // hidden.
15603 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype, 15601 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
15604 PrototypeIterator::END_AT_NON_HIDDEN); 15602 PrototypeIterator::END_AT_NON_HIDDEN);
15605 while (!iter.IsAtEnd()) { 15603 while (!iter.IsAtEnd()) {
15606 // Casting to JSObject is fine because hidden prototypes are never 15604 // Casting to JSObject is fine because hidden prototypes are never
15607 // JSProxies. 15605 // JSProxies.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
15653 // Set the new prototype of the object. 15651 // Set the new prototype of the object.
15654 15652
15655 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); 15653 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
15656 15654
15657 PrototypeOptimizationMode mode = 15655 PrototypeOptimizationMode mode =
15658 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 15656 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
15659 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); 15657 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
15660 DCHECK(new_map->prototype() == *value); 15658 DCHECK(new_map->prototype() == *value);
15661 JSObject::MigrateToMap(real_receiver, new_map); 15659 JSObject::MigrateToMap(real_receiver, new_map);
15662 15660
15663 if (from_javascript && !dictionary_elements_in_chain &&
15664 new_map->DictionaryElementsInPrototypeChainOnly()) {
15665 // If the prototype chain didn't previously have element callbacks, then
15666 // KeyedStoreICs need to be cleared to ensure any that involve this
15667 // map go generic.
15668 TypeFeedbackVector::ClearAllKeyedStoreICs(isolate);
15669 }
15670
15671 heap->ClearInstanceofCache(); 15661 heap->ClearInstanceofCache();
15672 DCHECK(size == object->Size()); 15662 DCHECK(size == object->Size());
15673 return Just(true); 15663 return Just(true);
15674 } 15664 }
15675 15665
15676 // static 15666 // static
15677 void JSObject::SetImmutableProto(Handle<JSObject> object) { 15667 void JSObject::SetImmutableProto(Handle<JSObject> object) {
15678 DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS 15668 DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS
15679 Handle<Map> map(object->map()); 15669 Handle<Map> map(object->map());
15680 15670
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after
17357 uint32_t key = NumberToUint32(k); 17347 uint32_t key = NumberToUint32(k);
17358 if (key < limit) { 17348 if (key < limit) {
17359 if (value->IsUndefined(isolate)) { 17349 if (value->IsUndefined(isolate)) {
17360 undefs++; 17350 undefs++;
17361 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 17351 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17362 // Adding an entry with the key beyond smi-range requires 17352 // Adding an entry with the key beyond smi-range requires
17363 // allocation. Bailout. 17353 // allocation. Bailout.
17364 return bailout; 17354 return bailout;
17365 } else { 17355 } else {
17366 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17356 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17367 new_dict, pos, value, details, object->map()->is_prototype_map()); 17357 new_dict, pos, value, details, object);
17368 DCHECK(result.is_identical_to(new_dict)); 17358 DCHECK(result.is_identical_to(new_dict));
17369 USE(result); 17359 USE(result);
17370 pos++; 17360 pos++;
17371 } 17361 }
17372 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { 17362 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
17373 // Adding an entry with the key beyond smi-range requires 17363 // Adding an entry with the key beyond smi-range requires
17374 // allocation. Bailout. 17364 // allocation. Bailout.
17375 return bailout; 17365 return bailout;
17376 } else { 17366 } else {
17377 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17367 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17378 new_dict, key, value, details, object->map()->is_prototype_map()); 17368 new_dict, key, value, details, object);
17379 DCHECK(result.is_identical_to(new_dict)); 17369 DCHECK(result.is_identical_to(new_dict));
17380 USE(result); 17370 USE(result);
17381 } 17371 }
17382 } 17372 }
17383 17373
17384 uint32_t result = pos; 17374 uint32_t result = pos;
17385 PropertyDetails no_details = PropertyDetails::Empty(); 17375 PropertyDetails no_details = PropertyDetails::Empty();
17386 while (undefs > 0) { 17376 while (undefs > 0) {
17387 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 17377 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17388 // Adding an entry with the key beyond smi-range requires 17378 // Adding an entry with the key beyond smi-range requires
17389 // allocation. Bailout. 17379 // allocation. Bailout.
17390 return bailout; 17380 return bailout;
17391 } 17381 }
17392 HandleScope scope(isolate); 17382 HandleScope scope(isolate);
17393 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17383 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17394 new_dict, pos, isolate->factory()->undefined_value(), no_details, 17384 new_dict, pos, isolate->factory()->undefined_value(), no_details,
17395 object->map()->is_prototype_map()); 17385 object);
17396 DCHECK(result.is_identical_to(new_dict)); 17386 DCHECK(result.is_identical_to(new_dict));
17397 USE(result); 17387 USE(result);
17398 pos++; 17388 pos++;
17399 undefs--; 17389 undefs--;
17400 } 17390 }
17401 17391
17402 object->set_elements(*new_dict); 17392 object->set_elements(*new_dict);
17403 17393
17404 AllowHeapAllocation allocate_return_value; 17394 AllowHeapAllocation allocate_return_value;
17405 return isolate->factory()->NewNumberFromUint(result); 17395 return isolate->factory()->NewNumberFromUint(result);
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after
18253 if (!this->IsKey(isolate, k)) continue; 18243 if (!this->IsKey(isolate, k)) continue;
18254 DCHECK(!IsDeleted(i)); 18244 DCHECK(!IsDeleted(i));
18255 PropertyDetails details = this->DetailsAt(i); 18245 PropertyDetails details = this->DetailsAt(i);
18256 if (details.type() == ACCESSOR_CONSTANT) return true; 18246 if (details.type() == ACCESSOR_CONSTANT) return true;
18257 PropertyAttributes attr = details.attributes(); 18247 PropertyAttributes attr = details.attributes();
18258 if (attr & ALL_ATTRIBUTES_MASK) return true; 18248 if (attr & ALL_ATTRIBUTES_MASK) return true;
18259 } 18249 }
18260 return false; 18250 return false;
18261 } 18251 }
18262 18252
18263 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key, 18253 void SeededNumberDictionary::UpdateMaxNumberKey(
18264 bool used_as_prototype) { 18254 uint32_t key, Handle<JSObject> dictionary_holder) {
18265 DisallowHeapAllocation no_allocation; 18255 DisallowHeapAllocation no_allocation;
18266 // If the dictionary requires slow elements an element has already 18256 // If the dictionary requires slow elements an element has already
18267 // been added at a high index. 18257 // been added at a high index.
18268 if (requires_slow_elements()) return; 18258 if (requires_slow_elements()) return;
18269 // Check if this index is high enough that we should require slow 18259 // Check if this index is high enough that we should require slow
18270 // elements. 18260 // elements.
18271 if (key > kRequiresSlowElementsLimit) { 18261 if (key > kRequiresSlowElementsLimit) {
18272 if (used_as_prototype) { 18262 if (!dictionary_holder.is_null()) {
18273 // TODO(verwaest): Remove this hack. 18263 dictionary_holder->RequireSlowElements(this);
18274 TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
18275 } 18264 }
18276 set_requires_slow_elements(); 18265 set_requires_slow_elements();
18277 return; 18266 return;
18278 } 18267 }
18279 // Update max key value. 18268 // Update max key value.
18280 Object* max_index_object = get(kMaxNumberKeyIndex); 18269 Object* max_index_object = get(kMaxNumberKeyIndex);
18281 if (!max_index_object->IsSmi() || max_number_key() < key) { 18270 if (!max_index_object->IsSmi() || max_number_key() < key) {
18282 FixedArray::set(kMaxNumberKeyIndex, 18271 FixedArray::set(kMaxNumberKeyIndex,
18283 Smi::FromInt(key << kRequiresSlowElementsTagSize)); 18272 Smi::FromInt(key << kRequiresSlowElementsTagSize));
18284 } 18273 }
18285 } 18274 }
18286 18275
18287
18288 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( 18276 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
18289 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18277 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18290 Handle<Object> value, PropertyDetails details, bool used_as_prototype) { 18278 Handle<Object> value, PropertyDetails details,
18291 dictionary->UpdateMaxNumberKey(key, used_as_prototype); 18279 Handle<JSObject> dictionary_holder) {
18280 dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18292 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); 18281 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18293 return Add(dictionary, key, value, details); 18282 return Add(dictionary, key, value, details);
18294 } 18283 }
18295 18284
18296 18285
18297 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( 18286 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
18298 Handle<UnseededNumberDictionary> dictionary, 18287 Handle<UnseededNumberDictionary> dictionary,
18299 uint32_t key, 18288 uint32_t key,
18300 Handle<Object> value) { 18289 Handle<Object> value) {
18301 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); 18290 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18302 return Add(dictionary, key, value, PropertyDetails::Empty()); 18291 return Add(dictionary, key, value, PropertyDetails::Empty());
18303 } 18292 }
18304 18293
18305 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey( 18294 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey(
18306 Handle<UnseededNumberDictionary> dictionary, uint32_t key) { 18295 Handle<UnseededNumberDictionary> dictionary, uint32_t key) {
18307 int entry = dictionary->FindEntry(key); 18296 int entry = dictionary->FindEntry(key);
18308 if (entry == kNotFound) return dictionary; 18297 if (entry == kNotFound) return dictionary;
18309 18298
18310 Factory* factory = dictionary->GetIsolate()->factory(); 18299 Factory* factory = dictionary->GetIsolate()->factory();
18311 dictionary->SetEntry(entry, factory->the_hole_value(), 18300 dictionary->SetEntry(entry, factory->the_hole_value(),
18312 factory->the_hole_value()); 18301 factory->the_hole_value());
18313 dictionary->ElementRemoved(); 18302 dictionary->ElementRemoved();
18314 return dictionary->Shrink(dictionary, key); 18303 return dictionary->Shrink(dictionary, key);
18315 } 18304 }
18316 18305
18317 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( 18306 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
18318 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18307 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18319 Handle<Object> value, bool used_as_prototype) { 18308 Handle<Object> value, Handle<JSObject> dictionary_holder) {
18320 dictionary->UpdateMaxNumberKey(key, used_as_prototype); 18309 dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18321 return AtPut(dictionary, key, value); 18310 return AtPut(dictionary, key, value);
18322 } 18311 }
18323 18312
18324 18313
18325 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut( 18314 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
18326 Handle<UnseededNumberDictionary> dictionary, 18315 Handle<UnseededNumberDictionary> dictionary,
18327 uint32_t key, 18316 uint32_t key,
18328 Handle<Object> value) { 18317 Handle<Object> value) {
18329 return AtPut(dictionary, key, value); 18318 return AtPut(dictionary, key, value);
18330 } 18319 }
18331 18320
18332
18333 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( 18321 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
18334 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18322 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18335 Handle<Object> value, PropertyDetails details, bool used_as_prototype) { 18323 Handle<Object> value, PropertyDetails details,
18324 Handle<JSObject> dictionary_holder) {
18336 int entry = dictionary->FindEntry(key); 18325 int entry = dictionary->FindEntry(key);
18337 if (entry == kNotFound) { 18326 if (entry == kNotFound) {
18338 return AddNumberEntry(dictionary, key, value, details, used_as_prototype); 18327 return AddNumberEntry(dictionary, key, value, details, dictionary_holder);
18339 } 18328 }
18340 // Preserve enumeration index. 18329 // Preserve enumeration index.
18341 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); 18330 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
18342 Handle<Object> object_key = 18331 Handle<Object> object_key =
18343 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); 18332 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
18344 dictionary->SetEntry(entry, object_key, value, details); 18333 dictionary->SetEntry(entry, object_key, value, details);
18345 return dictionary; 18334 return dictionary;
18346 } 18335 }
18347 18336
18348 18337
(...skipping 2167 matching lines...) Expand 10 before | Expand all | Expand 10 after
20516 // depend on this. 20505 // depend on this.
20517 return DICTIONARY_ELEMENTS; 20506 return DICTIONARY_ELEMENTS;
20518 } 20507 }
20519 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20508 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20520 return kind; 20509 return kind;
20521 } 20510 }
20522 } 20511 }
20523 20512
20524 } // namespace internal 20513 } // namespace internal
20525 } // namespace v8 20514 } // namespace v8
OLDNEW
« src/ic/accessor-assembler.cc ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698