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

Side by Side Diff: src/lookup.cc

Issue 2598543003: [runtime][ic] Constant field tracking support. (Closed)
Patch Set: Addressing comments Created 3 years, 10 months 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/lookup.h ('k') | src/map-updater.h » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/lookup.h" 5 #include "src/lookup.h"
6 6
7 #include "src/bootstrapper.h" 7 #include "src/bootstrapper.h"
8 #include "src/deoptimizer.h" 8 #include "src/deoptimizer.h"
9 #include "src/elements.h" 9 #include "src/elements.h"
10 #include "src/field-type.h" 10 #include "src/field-type.h"
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 Handle<PropertyCell> cell( 230 Handle<PropertyCell> cell(
231 PropertyCell::cast(dictionary->ValueAt(dictionary_entry()))); 231 PropertyCell::cast(dictionary->ValueAt(dictionary_entry())));
232 DCHECK(!cell->IsTheHole(isolate_)); 232 DCHECK(!cell->IsTheHole(isolate_));
233 property_details_ = cell->property_details(); 233 property_details_ = cell->property_details();
234 PropertyCell::PrepareForValue(dictionary, dictionary_entry(), value, 234 PropertyCell::PrepareForValue(dictionary, dictionary_entry(), value,
235 property_details_); 235 property_details_);
236 return; 236 return;
237 } 237 }
238 if (!holder->HasFastProperties()) return; 238 if (!holder->HasFastProperties()) return;
239 239
240 PropertyConstness new_constness = kConst;
241 if (FLAG_track_constant_fields) {
242 if (constness() == kConst) {
243 DCHECK_EQ(kData, property_details_.kind());
244 // Check that current value matches new value otherwise we should make
245 // the property mutable.
246 if (!IsConstFieldValueEqualTo(*value)) new_constness = kMutable;
247 }
248 } else {
249 new_constness = kMutable;
250 }
251
240 Handle<Map> old_map(holder->map(), isolate_); 252 Handle<Map> old_map(holder->map(), isolate_);
241 Handle<Map> new_map = 253 Handle<Map> new_map = Map::PrepareForDataProperty(
242 Map::PrepareForDataProperty(old_map, descriptor_number(), value); 254 old_map, descriptor_number(), new_constness, value);
243 255
244 if (old_map.is_identical_to(new_map)) { 256 if (old_map.is_identical_to(new_map)) {
245 // Update the property details if the representation was None. 257 // Update the property details if the representation was None.
246 if (representation().IsNone()) { 258 if (representation().IsNone()) {
247 property_details_ = 259 property_details_ =
248 new_map->instance_descriptors()->GetDetails(descriptor_number()); 260 new_map->instance_descriptors()->GetDetails(descriptor_number());
249 } 261 }
250 return; 262 return;
251 } 263 }
252 264
(...skipping 11 matching lines...) Expand all
264 DCHECK(!holder->HasFixedTypedArrayElements()); 276 DCHECK(!holder->HasFixedTypedArrayElements());
265 DCHECK(attributes != NONE || !holder->HasFastElements()); 277 DCHECK(attributes != NONE || !holder->HasFastElements());
266 Handle<FixedArrayBase> elements(holder->elements()); 278 Handle<FixedArrayBase> elements(holder->elements());
267 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value, 279 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value,
268 attributes); 280 attributes);
269 ReloadPropertyInformation<true>(); 281 ReloadPropertyInformation<true>();
270 } else if (holder->HasFastProperties()) { 282 } else if (holder->HasFastProperties()) {
271 Handle<Map> old_map(holder->map(), isolate_); 283 Handle<Map> old_map(holder->map(), isolate_);
272 Handle<Map> new_map = Map::ReconfigureExistingProperty( 284 Handle<Map> new_map = Map::ReconfigureExistingProperty(
273 old_map, descriptor_number(), i::kData, attributes); 285 old_map, descriptor_number(), i::kData, attributes);
274 new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value); 286 // Force mutable to avoid changing constant value by reconfiguring
287 // kData -> kAccessor -> kData.
288 new_map = Map::PrepareForDataProperty(new_map, descriptor_number(),
289 kMutable, value);
275 JSObject::MigrateToMap(holder, new_map); 290 JSObject::MigrateToMap(holder, new_map);
276 ReloadPropertyInformation<false>(); 291 ReloadPropertyInformation<false>();
277 } else { 292 } else {
278 PropertyDetails details(kData, attributes, 0, PropertyCellType::kMutable); 293 PropertyDetails details(kData, attributes, 0, PropertyCellType::kMutable);
279 if (holder->IsJSGlobalObject()) { 294 if (holder->IsJSGlobalObject()) {
280 Handle<GlobalDictionary> dictionary(holder->global_dictionary()); 295 Handle<GlobalDictionary> dictionary(holder->global_dictionary());
281 296
282 Handle<PropertyCell> cell = PropertyCell::PrepareForValue( 297 Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
283 dictionary, dictionary_entry(), value, details); 298 dictionary, dictionary_entry(), value, details);
284 cell->set_value(*value); 299 cell->set_value(*value);
285 property_details_ = cell->property_details(); 300 property_details_ = cell->property_details();
286 } else { 301 } else {
287 Handle<NameDictionary> dictionary(holder->property_dictionary()); 302 Handle<NameDictionary> dictionary(holder->property_dictionary());
288 PropertyDetails original_details = 303 PropertyDetails original_details =
289 dictionary->DetailsAt(dictionary_entry()); 304 dictionary->DetailsAt(dictionary_entry());
290 int enumeration_index = original_details.dictionary_index(); 305 int enumeration_index = original_details.dictionary_index();
291 DCHECK(enumeration_index > 0); 306 DCHECK(enumeration_index > 0);
292 details = details.set_index(enumeration_index); 307 details = details.set_index(enumeration_index);
293 dictionary->SetEntry(dictionary_entry(), name(), value, details); 308 dictionary->SetEntry(dictionary_entry(), name(), value, details);
294 property_details_ = details; 309 property_details_ = details;
295 } 310 }
296 state_ = DATA; 311 state_ = DATA;
297 } 312 }
298 313
299 WriteDataValue(value); 314 WriteDataValue(value, true);
300 315
301 #if VERIFY_HEAP 316 #if VERIFY_HEAP
302 if (FLAG_verify_heap) { 317 if (FLAG_verify_heap) {
303 holder->JSObjectVerify(); 318 holder->JSObjectVerify();
304 } 319 }
305 #endif 320 #endif
306 } 321 }
307 322
308 // Can only be called when the receiver is a JSObject. JSProxy has to be handled 323 // Can only be called when the receiver is a JSObject. JSProxy has to be handled
309 // via a trap. Adding properties to primitive values is not observable. 324 // via a trap. Adding properties to primitive values is not observable.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 has_property_ = true; 368 has_property_ = true;
354 } else { 369 } else {
355 // Don't set enumeration index (it will be set during value store). 370 // Don't set enumeration index (it will be set during value store).
356 property_details_ = 371 property_details_ =
357 PropertyDetails(kData, attributes, 0, PropertyCellType::kNoCell); 372 PropertyDetails(kData, attributes, 0, PropertyCellType::kNoCell);
358 transition_ = map; 373 transition_ = map;
359 } 374 }
360 return; 375 return;
361 } 376 }
362 377
363 Handle<Map> transition = 378 Handle<Map> transition = Map::TransitionToDataProperty(
364 Map::TransitionToDataProperty(map, name_, value, attributes, store_mode); 379 map, name_, value, attributes, kDefaultFieldConstness, store_mode);
365 state_ = TRANSITION; 380 state_ = TRANSITION;
366 transition_ = transition; 381 transition_ = transition;
367 382
368 if (transition->is_dictionary_map()) { 383 if (transition->is_dictionary_map()) {
369 // Don't set enumeration index (it will be set during value store). 384 // Don't set enumeration index (it will be set during value store).
370 property_details_ = 385 property_details_ =
371 PropertyDetails(kData, attributes, 0, PropertyCellType::kNoCell); 386 PropertyDetails(kData, attributes, 0, PropertyCellType::kNoCell);
372 } else { 387 } else {
373 property_details_ = transition->GetLastDescriptorDetails(); 388 property_details_ = transition->GetLastDescriptorDetails();
374 has_property_ = true; 389 has_property_ = true;
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 Handle<JSObject> holder = GetHolder<JSObject>(); 611 Handle<JSObject> holder = GetHolder<JSObject>();
597 FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_); 612 FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_);
598 return JSObject::FastPropertyAt(holder, property_details_.representation(), 613 return JSObject::FastPropertyAt(holder, property_details_.representation(),
599 field_index); 614 field_index);
600 } else { 615 } else {
601 result = holder_->map()->instance_descriptors()->GetValue(number_); 616 result = holder_->map()->instance_descriptors()->GetValue(number_);
602 } 617 }
603 return handle(result, isolate_); 618 return handle(result, isolate_);
604 } 619 }
605 620
621 bool LookupIterator::IsConstFieldValueEqualTo(Object* value) const {
622 DCHECK(!IsElement());
623 DCHECK(holder_->HasFastProperties());
624 DCHECK_EQ(kField, property_details_.location());
625 DCHECK_EQ(kConst, property_details_.constness());
626 Handle<JSObject> holder = GetHolder<JSObject>();
627 FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_);
628 if (property_details_.representation().IsDouble()) {
629 if (!value->IsNumber()) return false;
630 uint64_t bits;
631 if (holder->IsUnboxedDoubleField(field_index)) {
632 bits = holder->RawFastDoublePropertyAsBitsAt(field_index);
633 } else {
634 Object* current_value = holder->RawFastPropertyAt(field_index);
635 DCHECK(current_value->IsMutableHeapNumber());
636 bits = HeapNumber::cast(current_value)->value_as_bits();
637 }
638 // Use bit representation of double to to check for hole double, since
639 // manipulating the signaling NaN used for the hole in C++, e.g. with
640 // bit_cast or value(), will change its value on ia32 (the x87 stack is
641 // used to return values and stores to the stack silently clear the
642 // signalling bit).
643 if (bits == kHoleNanInt64) {
644 // Uninitialized double field.
645 return true;
646 }
647 return bit_cast<double>(bits) == value->Number();
648 } else {
649 Object* current_value = holder->RawFastPropertyAt(field_index);
650 return current_value->IsUninitialized(isolate()) || current_value == value;
651 }
652 }
653
606 int LookupIterator::GetFieldDescriptorIndex() const { 654 int LookupIterator::GetFieldDescriptorIndex() const {
607 DCHECK(has_property_); 655 DCHECK(has_property_);
608 DCHECK(holder_->HasFastProperties()); 656 DCHECK(holder_->HasFastProperties());
609 DCHECK_EQ(kField, property_details_.location()); 657 DCHECK_EQ(kField, property_details_.location());
610 DCHECK_EQ(kData, property_details_.kind()); 658 DCHECK_EQ(kData, property_details_.kind());
611 return descriptor_number(); 659 return descriptor_number();
612 } 660 }
613 661
614 int LookupIterator::GetAccessorIndex() const { 662 int LookupIterator::GetAccessorIndex() const {
615 DCHECK(has_property_); 663 DCHECK(has_property_);
616 DCHECK(holder_->HasFastProperties()); 664 DCHECK(holder_->HasFastProperties());
617 DCHECK_EQ(kDescriptor, property_details_.location()); 665 DCHECK_EQ(kDescriptor, property_details_.location());
618 DCHECK_EQ(kAccessor, property_details_.kind()); 666 DCHECK_EQ(kAccessor, property_details_.kind());
619 return descriptor_number(); 667 return descriptor_number();
620 } 668 }
621 669
622 670
623 int LookupIterator::GetConstantIndex() const { 671 int LookupIterator::GetConstantIndex() const {
624 DCHECK(has_property_); 672 DCHECK(has_property_);
625 DCHECK(holder_->HasFastProperties()); 673 DCHECK(holder_->HasFastProperties());
626 DCHECK_EQ(kDescriptor, property_details_.location()); 674 DCHECK_EQ(kDescriptor, property_details_.location());
627 DCHECK_EQ(kData, property_details_.kind()); 675 DCHECK_EQ(kData, property_details_.kind());
676 DCHECK(!FLAG_track_constant_fields);
628 DCHECK(!IsElement()); 677 DCHECK(!IsElement());
629 return descriptor_number(); 678 return descriptor_number();
630 } 679 }
631 680
632 681
633 FieldIndex LookupIterator::GetFieldIndex() const { 682 FieldIndex LookupIterator::GetFieldIndex() const {
634 DCHECK(has_property_); 683 DCHECK(has_property_);
635 DCHECK(holder_->HasFastProperties()); 684 DCHECK(holder_->HasFastProperties());
636 DCHECK_EQ(kField, property_details_.location()); 685 DCHECK_EQ(kField, property_details_.location());
637 DCHECK(!IsElement()); 686 DCHECK(!IsElement());
(...skipping 28 matching lines...) Expand all
666 return FetchValue(); 715 return FetchValue();
667 } 716 }
668 717
669 718
670 Handle<Object> LookupIterator::GetDataValue() const { 719 Handle<Object> LookupIterator::GetDataValue() const {
671 DCHECK_EQ(DATA, state_); 720 DCHECK_EQ(DATA, state_);
672 Handle<Object> value = FetchValue(); 721 Handle<Object> value = FetchValue();
673 return value; 722 return value;
674 } 723 }
675 724
676 725 void LookupIterator::WriteDataValue(Handle<Object> value,
677 void LookupIterator::WriteDataValue(Handle<Object> value) { 726 bool initializing_store) {
678 DCHECK_EQ(DATA, state_); 727 DCHECK_EQ(DATA, state_);
679 Handle<JSReceiver> holder = GetHolder<JSReceiver>(); 728 Handle<JSReceiver> holder = GetHolder<JSReceiver>();
680 if (IsElement()) { 729 if (IsElement()) {
681 Handle<JSObject> object = Handle<JSObject>::cast(holder); 730 Handle<JSObject> object = Handle<JSObject>::cast(holder);
682 ElementsAccessor* accessor = object->GetElementsAccessor(); 731 ElementsAccessor* accessor = object->GetElementsAccessor();
683 accessor->Set(object, number_, *value); 732 accessor->Set(object, number_, *value);
684 } else if (holder->HasFastProperties()) { 733 } else if (holder->HasFastProperties()) {
685 if (property_details_.location() == kField) { 734 if (property_details_.location() == kField) {
735 // Check that in case of kConst field the existing value is equal to
736 // |value|.
737 DCHECK_IMPLIES(
738 !initializing_store && property_details_.constness() == kConst,
739 IsConstFieldValueEqualTo(*value));
686 JSObject::cast(*holder)->WriteToField(descriptor_number(), 740 JSObject::cast(*holder)->WriteToField(descriptor_number(),
687 property_details_, *value); 741 property_details_, *value);
688 } else { 742 } else {
689 DCHECK_EQ(kDescriptor, property_details_.location()); 743 DCHECK_EQ(kDescriptor, property_details_.location());
690 DCHECK_EQ(kConst, property_details_.constness()); 744 DCHECK_EQ(kConst, property_details_.constness());
691 } 745 }
692 } else if (holder->IsJSGlobalObject()) { 746 } else if (holder->IsJSGlobalObject()) {
693 GlobalDictionary* dictionary = JSObject::cast(*holder)->global_dictionary(); 747 GlobalDictionary* dictionary = JSObject::cast(*holder)->global_dictionary();
694 Object* cell = dictionary->ValueAt(dictionary_entry()); 748 Object* cell = dictionary->ValueAt(dictionary_entry());
695 DCHECK(cell->IsPropertyCell()); 749 DCHECK(cell->IsPropertyCell());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 927
874 // We have found a cached property! Modify the iterator accordingly. 928 // We have found a cached property! Modify the iterator accordingly.
875 name_ = maybe_name.ToHandleChecked(); 929 name_ = maybe_name.ToHandleChecked();
876 Restart(); 930 Restart();
877 CHECK_EQ(state(), LookupIterator::DATA); 931 CHECK_EQ(state(), LookupIterator::DATA);
878 return true; 932 return true;
879 } 933 }
880 934
881 } // namespace internal 935 } // namespace internal
882 } // namespace v8 936 } // namespace v8
OLDNEW
« no previous file with comments | « src/lookup.h ('k') | src/map-updater.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698