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

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: 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 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 // TODO(verwaest): Remove this hack.
Jakob Kummerow 2016/11/28 18:48:05 I think you're addressing this TODO :-)
Igor Sheludko 2016/11/28 22:25:54 Done.
6157 if (map()->is_prototype_map()) { 6157 if (map()->is_prototype_map()) {
6158 TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate()); 6158 // If this object is a prototype (the callee will check), invalidate any
6159 // prototype chains involving it.
6160 InvalidatePrototypeChains(map());
6159 } 6161 }
6160 } 6162 }
6161 6163
6162 6164
6163 Handle<SeededNumberDictionary> JSObject::NormalizeElements( 6165 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
6164 Handle<JSObject> object) { 6166 Handle<JSObject> object) {
6165 DCHECK(!object->HasFixedTypedArrayElements()); 6167 DCHECK(!object->HasFixedTypedArrayElements());
6166 Isolate* isolate = object->GetIsolate(); 6168 Isolate* isolate = object->GetIsolate();
6167 bool is_arguments = object->HasSloppyArgumentsElements(); 6169 bool is_arguments = object->HasSloppyArgumentsElements();
6168 { 6170 {
(...skipping 9435 matching lines...) Expand 10 before | Expand all | Expand 10 after
15604 } 15606 }
15605 } else { 15607 } else {
15606 DCHECK(!object->IsAccessCheckNeeded()); 15608 DCHECK(!object->IsAccessCheckNeeded());
15607 } 15609 }
15608 15610
15609 Heap* heap = isolate->heap(); 15611 Heap* heap = isolate->heap();
15610 // Silently ignore the change if value is not a JSObject or null. 15612 // Silently ignore the change if value is not a JSObject or null.
15611 // SpiderMonkey behaves this way. 15613 // SpiderMonkey behaves this way.
15612 if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true); 15614 if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
15613 15615
15614 bool dictionary_elements_in_chain =
15615 object->map()->DictionaryElementsInPrototypeChainOnly();
15616
15617 bool all_extensible = object->map()->is_extensible(); 15616 bool all_extensible = object->map()->is_extensible();
15618 Handle<JSObject> real_receiver = object; 15617 Handle<JSObject> real_receiver = object;
15619 if (from_javascript) { 15618 if (from_javascript) {
15620 // Find the first object in the chain whose prototype object is not 15619 // Find the first object in the chain whose prototype object is not
15621 // hidden. 15620 // hidden.
15622 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype, 15621 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
15623 PrototypeIterator::END_AT_NON_HIDDEN); 15622 PrototypeIterator::END_AT_NON_HIDDEN);
15624 while (!iter.IsAtEnd()) { 15623 while (!iter.IsAtEnd()) {
15625 // Casting to JSObject is fine because hidden prototypes are never 15624 // Casting to JSObject is fine because hidden prototypes are never
15626 // JSProxies. 15625 // JSProxies.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
15672 // Set the new prototype of the object. 15671 // Set the new prototype of the object.
15673 15672
15674 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); 15673 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
15675 15674
15676 PrototypeOptimizationMode mode = 15675 PrototypeOptimizationMode mode =
15677 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 15676 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
15678 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); 15677 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
15679 DCHECK(new_map->prototype() == *value); 15678 DCHECK(new_map->prototype() == *value);
15680 JSObject::MigrateToMap(real_receiver, new_map); 15679 JSObject::MigrateToMap(real_receiver, new_map);
15681 15680
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
15690 heap->ClearInstanceofCache(); 15681 heap->ClearInstanceofCache();
15691 DCHECK(size == object->Size()); 15682 DCHECK(size == object->Size());
15692 return Just(true); 15683 return Just(true);
15693 } 15684 }
15694 15685
15695 // static 15686 // static
15696 void JSObject::SetImmutableProto(Handle<JSObject> object) { 15687 void JSObject::SetImmutableProto(Handle<JSObject> object) {
15697 DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS 15688 DCHECK(!object->IsAccessCheckNeeded()); // Never called from JS
15698 Handle<Map> map(object->map()); 15689 Handle<Map> map(object->map());
15699 15690
(...skipping 1676 matching lines...) Expand 10 before | Expand all | Expand 10 after
17376 uint32_t key = NumberToUint32(k); 17367 uint32_t key = NumberToUint32(k);
17377 if (key < limit) { 17368 if (key < limit) {
17378 if (value->IsUndefined(isolate)) { 17369 if (value->IsUndefined(isolate)) {
17379 undefs++; 17370 undefs++;
17380 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 17371 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17381 // Adding an entry with the key beyond smi-range requires 17372 // Adding an entry with the key beyond smi-range requires
17382 // allocation. Bailout. 17373 // allocation. Bailout.
17383 return bailout; 17374 return bailout;
17384 } else { 17375 } else {
17385 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17376 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17386 new_dict, pos, value, details, object->map()->is_prototype_map()); 17377 new_dict, pos, value, details, object);
17387 DCHECK(result.is_identical_to(new_dict)); 17378 DCHECK(result.is_identical_to(new_dict));
17388 USE(result); 17379 USE(result);
17389 pos++; 17380 pos++;
17390 } 17381 }
17391 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { 17382 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
17392 // Adding an entry with the key beyond smi-range requires 17383 // Adding an entry with the key beyond smi-range requires
17393 // allocation. Bailout. 17384 // allocation. Bailout.
17394 return bailout; 17385 return bailout;
17395 } else { 17386 } else {
17396 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17387 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17397 new_dict, key, value, details, object->map()->is_prototype_map()); 17388 new_dict, key, value, details, object);
17398 DCHECK(result.is_identical_to(new_dict)); 17389 DCHECK(result.is_identical_to(new_dict));
17399 USE(result); 17390 USE(result);
17400 } 17391 }
17401 } 17392 }
17402 17393
17403 uint32_t result = pos; 17394 uint32_t result = pos;
17404 PropertyDetails no_details = PropertyDetails::Empty(); 17395 PropertyDetails no_details = PropertyDetails::Empty();
17405 while (undefs > 0) { 17396 while (undefs > 0) {
17406 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { 17397 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
17407 // Adding an entry with the key beyond smi-range requires 17398 // Adding an entry with the key beyond smi-range requires
17408 // allocation. Bailout. 17399 // allocation. Bailout.
17409 return bailout; 17400 return bailout;
17410 } 17401 }
17411 HandleScope scope(isolate); 17402 HandleScope scope(isolate);
17412 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( 17403 Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
17413 new_dict, pos, isolate->factory()->undefined_value(), no_details, 17404 new_dict, pos, isolate->factory()->undefined_value(), no_details,
17414 object->map()->is_prototype_map()); 17405 object);
17415 DCHECK(result.is_identical_to(new_dict)); 17406 DCHECK(result.is_identical_to(new_dict));
17416 USE(result); 17407 USE(result);
17417 pos++; 17408 pos++;
17418 undefs--; 17409 undefs--;
17419 } 17410 }
17420 17411
17421 object->set_elements(*new_dict); 17412 object->set_elements(*new_dict);
17422 17413
17423 AllowHeapAllocation allocate_return_value; 17414 AllowHeapAllocation allocate_return_value;
17424 return isolate->factory()->NewNumberFromUint(result); 17415 return isolate->factory()->NewNumberFromUint(result);
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after
18176 if (!this->IsKey(isolate, k)) continue; 18167 if (!this->IsKey(isolate, k)) continue;
18177 DCHECK(!IsDeleted(i)); 18168 DCHECK(!IsDeleted(i));
18178 PropertyDetails details = this->DetailsAt(i); 18169 PropertyDetails details = this->DetailsAt(i);
18179 if (details.type() == ACCESSOR_CONSTANT) return true; 18170 if (details.type() == ACCESSOR_CONSTANT) return true;
18180 PropertyAttributes attr = details.attributes(); 18171 PropertyAttributes attr = details.attributes();
18181 if (attr & ALL_ATTRIBUTES_MASK) return true; 18172 if (attr & ALL_ATTRIBUTES_MASK) return true;
18182 } 18173 }
18183 return false; 18174 return false;
18184 } 18175 }
18185 18176
18186 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key, 18177 void SeededNumberDictionary::UpdateMaxNumberKey(
18187 bool used_as_prototype) { 18178 uint32_t key, Handle<JSObject> dictionary_holder) {
18188 DisallowHeapAllocation no_allocation; 18179 DisallowHeapAllocation no_allocation;
18189 // If the dictionary requires slow elements an element has already 18180 // If the dictionary requires slow elements an element has already
18190 // been added at a high index. 18181 // been added at a high index.
18191 if (requires_slow_elements()) return; 18182 if (requires_slow_elements()) return;
18192 // Check if this index is high enough that we should require slow 18183 // Check if this index is high enough that we should require slow
18193 // elements. 18184 // elements.
18194 if (key > kRequiresSlowElementsLimit) { 18185 if (key > kRequiresSlowElementsLimit) {
18195 if (used_as_prototype) { 18186 if (!dictionary_holder.is_null()) {
18196 // TODO(verwaest): Remove this hack. 18187 dictionary_holder->RequireSlowElements(this);
18197 TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
18198 } 18188 }
18199 set_requires_slow_elements(); 18189 set_requires_slow_elements();
18200 return; 18190 return;
18201 } 18191 }
18202 // Update max key value. 18192 // Update max key value.
18203 Object* max_index_object = get(kMaxNumberKeyIndex); 18193 Object* max_index_object = get(kMaxNumberKeyIndex);
18204 if (!max_index_object->IsSmi() || max_number_key() < key) { 18194 if (!max_index_object->IsSmi() || max_number_key() < key) {
18205 FixedArray::set(kMaxNumberKeyIndex, 18195 FixedArray::set(kMaxNumberKeyIndex,
18206 Smi::FromInt(key << kRequiresSlowElementsTagSize)); 18196 Smi::FromInt(key << kRequiresSlowElementsTagSize));
18207 } 18197 }
18208 } 18198 }
18209 18199
18210
18211 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( 18200 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
18212 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18201 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18213 Handle<Object> value, PropertyDetails details, bool used_as_prototype) { 18202 Handle<Object> value, PropertyDetails details,
18214 dictionary->UpdateMaxNumberKey(key, used_as_prototype); 18203 Handle<JSObject> dictionary_holder) {
18204 dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18215 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); 18205 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18216 return Add(dictionary, key, value, details); 18206 return Add(dictionary, key, value, details);
18217 } 18207 }
18218 18208
18219 18209
18220 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( 18210 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
18221 Handle<UnseededNumberDictionary> dictionary, 18211 Handle<UnseededNumberDictionary> dictionary,
18222 uint32_t key, 18212 uint32_t key,
18223 Handle<Object> value) { 18213 Handle<Object> value) {
18224 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); 18214 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
18225 return Add(dictionary, key, value, PropertyDetails::Empty()); 18215 return Add(dictionary, key, value, PropertyDetails::Empty());
18226 } 18216 }
18227 18217
18228 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey( 18218 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey(
18229 Handle<UnseededNumberDictionary> dictionary, uint32_t key) { 18219 Handle<UnseededNumberDictionary> dictionary, uint32_t key) {
18230 int entry = dictionary->FindEntry(key); 18220 int entry = dictionary->FindEntry(key);
18231 if (entry == kNotFound) return dictionary; 18221 if (entry == kNotFound) return dictionary;
18232 18222
18233 Factory* factory = dictionary->GetIsolate()->factory(); 18223 Factory* factory = dictionary->GetIsolate()->factory();
18234 dictionary->SetEntry(entry, factory->the_hole_value(), 18224 dictionary->SetEntry(entry, factory->the_hole_value(),
18235 factory->the_hole_value()); 18225 factory->the_hole_value());
18236 dictionary->ElementRemoved(); 18226 dictionary->ElementRemoved();
18237 return dictionary->Shrink(dictionary, key); 18227 return dictionary->Shrink(dictionary, key);
18238 } 18228 }
18239 18229
18240 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( 18230 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
18241 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18231 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18242 Handle<Object> value, bool used_as_prototype) { 18232 Handle<Object> value, Handle<JSObject> dictionary_holder) {
18243 dictionary->UpdateMaxNumberKey(key, used_as_prototype); 18233 dictionary->UpdateMaxNumberKey(key, dictionary_holder);
18244 return AtPut(dictionary, key, value); 18234 return AtPut(dictionary, key, value);
18245 } 18235 }
18246 18236
18247 18237
18248 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut( 18238 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
18249 Handle<UnseededNumberDictionary> dictionary, 18239 Handle<UnseededNumberDictionary> dictionary,
18250 uint32_t key, 18240 uint32_t key,
18251 Handle<Object> value) { 18241 Handle<Object> value) {
18252 return AtPut(dictionary, key, value); 18242 return AtPut(dictionary, key, value);
18253 } 18243 }
18254 18244
18255
18256 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( 18245 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
18257 Handle<SeededNumberDictionary> dictionary, uint32_t key, 18246 Handle<SeededNumberDictionary> dictionary, uint32_t key,
18258 Handle<Object> value, PropertyDetails details, bool used_as_prototype) { 18247 Handle<Object> value, PropertyDetails details,
18248 Handle<JSObject> dictionary_holder) {
18259 int entry = dictionary->FindEntry(key); 18249 int entry = dictionary->FindEntry(key);
18260 if (entry == kNotFound) { 18250 if (entry == kNotFound) {
18261 return AddNumberEntry(dictionary, key, value, details, used_as_prototype); 18251 return AddNumberEntry(dictionary, key, value, details, dictionary_holder);
18262 } 18252 }
18263 // Preserve enumeration index. 18253 // Preserve enumeration index.
18264 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); 18254 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
18265 Handle<Object> object_key = 18255 Handle<Object> object_key =
18266 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); 18256 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
18267 dictionary->SetEntry(entry, object_key, value, details); 18257 dictionary->SetEntry(entry, object_key, value, details);
18268 return dictionary; 18258 return dictionary;
18269 } 18259 }
18270 18260
18271 18261
(...skipping 2167 matching lines...) Expand 10 before | Expand all | Expand 10 after
20439 // depend on this. 20429 // depend on this.
20440 return DICTIONARY_ELEMENTS; 20430 return DICTIONARY_ELEMENTS;
20441 } 20431 }
20442 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20432 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20443 return kind; 20433 return kind;
20444 } 20434 }
20445 } 20435 }
20446 20436
20447 } // namespace internal 20437 } // namespace internal
20448 } // namespace v8 20438 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698