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

Side by Side Diff: src/objects.cc

Issue 1702443002: [runtime] Minor tweaks to LookupIterator for performance (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment Created 4 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.cc ('k') | no next file » | 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 <sstream> 9 #include <sstream>
10 10
(...skipping 3146 matching lines...) Expand 10 before | Expand all | Expand 10 after
3157 InvalidatePrototypeChains(object->map()); 3157 InvalidatePrototypeChains(object->map());
3158 Handle<Map> old_map(object->map()); 3158 Handle<Map> old_map(object->map());
3159 3159
3160 // If the map was registered with its prototype before, ensure that it 3160 // If the map was registered with its prototype before, ensure that it
3161 // registers with its new prototype now. This preserves the invariant that 3161 // registers with its new prototype now. This preserves the invariant that
3162 // when a map on a prototype chain is registered with its prototype, then 3162 // when a map on a prototype chain is registered with its prototype, then
3163 // all prototypes further up the chain are also registered with their 3163 // all prototypes further up the chain are also registered with their
3164 // respective prototypes. 3164 // respective prototypes.
3165 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate()); 3165 UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate());
3166 3166
3167 if (object->HasFastProperties()) { 3167 if (old_map->is_dictionary_map()) {
3168 if (!new_map->is_dictionary_map()) {
3169 MigrateFastToFast(object, new_map);
3170 if (old_map->is_prototype_map()) {
3171 DCHECK(!old_map->is_stable());
3172 DCHECK(new_map->is_stable());
3173 // Clear out the old descriptor array to avoid problems to sharing
3174 // the descriptor array without using an explicit.
3175 old_map->InitializeDescriptors(
3176 old_map->GetHeap()->empty_descriptor_array(),
3177 LayoutDescriptor::FastPointerLayout());
3178 // Ensure that no transition was inserted for prototype migrations.
3179 DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
3180 old_map->raw_transitions()));
3181 DCHECK(new_map->GetBackPointer()->IsUndefined());
3182 }
3183 } else {
3184 MigrateFastToSlow(object, new_map, expected_additional_properties);
3185 }
3186 } else {
3187 // For slow-to-fast migrations JSObject::MigrateSlowToFast() 3168 // For slow-to-fast migrations JSObject::MigrateSlowToFast()
3188 // must be used instead. 3169 // must be used instead.
3189 CHECK(new_map->is_dictionary_map()); 3170 CHECK(new_map->is_dictionary_map());
3190 3171
3191 // Slow-to-slow migration is trivial. 3172 // Slow-to-slow migration is trivial.
3192 object->set_map(*new_map); 3173 object->set_map(*new_map);
3174 } else if (!new_map->is_dictionary_map()) {
3175 MigrateFastToFast(object, new_map);
3176 if (old_map->is_prototype_map()) {
3177 DCHECK(!old_map->is_stable());
3178 DCHECK(new_map->is_stable());
3179 // Clear out the old descriptor array to avoid problems to sharing
3180 // the descriptor array without using an explicit.
3181 old_map->InitializeDescriptors(
3182 old_map->GetHeap()->empty_descriptor_array(),
3183 LayoutDescriptor::FastPointerLayout());
3184 // Ensure that no transition was inserted for prototype migrations.
3185 DCHECK_EQ(
3186 0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
3187 DCHECK(new_map->GetBackPointer()->IsUndefined());
3188 }
3189 } else {
3190 MigrateFastToSlow(object, new_map, expected_additional_properties);
3193 } 3191 }
3194 3192
3195 // Careful: Don't allocate here! 3193 // Careful: Don't allocate here!
3196 // For some callers of this method, |object| might be in an inconsistent 3194 // For some callers of this method, |object| might be in an inconsistent
3197 // state now: the new map might have a new elements_kind, but the object's 3195 // state now: the new map might have a new elements_kind, but the object's
3198 // elements pointer hasn't been updated yet. Callers will fix this, but in 3196 // elements pointer hasn't been updated yet. Callers will fix this, but in
3199 // the meantime, (indirectly) calling JSObjectVerify() must be avoided. 3197 // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
3200 // When adding code here, add a DisallowHeapAllocation too. 3198 // When adding code here, add a DisallowHeapAllocation too.
3201 } 3199 }
3202 3200
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
4601 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state()); 4599 DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
4602 4600
4603 Handle<JSObject> receiver = it->GetStoreTarget(); 4601 Handle<JSObject> receiver = it->GetStoreTarget();
4604 4602
4605 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) 4603 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
4606 // instead. If the prototype is Null, the proxy is detached. 4604 // instead. If the prototype is Null, the proxy is detached.
4607 if (receiver->IsJSGlobalProxy()) return Just(true); 4605 if (receiver->IsJSGlobalProxy()) return Just(true);
4608 4606
4609 Isolate* isolate = it->isolate(); 4607 Isolate* isolate = it->isolate();
4610 4608
4611 if (!receiver->map()->is_extensible() && 4609 if (it->ExtendingNonExtensible(receiver)) {
4612 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()))) {
4613 RETURN_FAILURE( 4610 RETURN_FAILURE(
4614 isolate, should_throw, 4611 isolate, should_throw,
4615 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName())); 4612 NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
4616 } 4613 }
4617 4614
4618 if (it->IsElement()) { 4615 if (it->IsElement()) {
4619 if (receiver->IsJSArray()) { 4616 if (receiver->IsJSArray()) {
4620 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 4617 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
4621 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) { 4618 if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
4622 RETURN_FAILURE(array->GetIsolate(), should_throw, 4619 RETURN_FAILURE(array->GetIsolate(), should_throw,
(...skipping 12 matching lines...) Expand all
4635 } 4632 }
4636 } 4633 }
4637 4634
4638 Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value, 4635 Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value,
4639 attributes, should_throw); 4636 attributes, should_throw);
4640 JSObject::ValidateElements(receiver); 4637 JSObject::ValidateElements(receiver);
4641 return result; 4638 return result;
4642 } else { 4639 } else {
4643 // Migrate to the most up-to-date map that will be able to store |value| 4640 // Migrate to the most up-to-date map that will be able to store |value|
4644 // under it->name() with |attributes|. 4641 // under it->name() with |attributes|.
4645 it->PrepareTransitionToDataProperty(value, attributes, store_mode); 4642 it->PrepareTransitionToDataProperty(receiver, value, attributes,
4643 store_mode);
4646 DCHECK_EQ(LookupIterator::TRANSITION, it->state()); 4644 DCHECK_EQ(LookupIterator::TRANSITION, it->state());
4647 it->ApplyTransitionToDataProperty(); 4645 it->ApplyTransitionToDataProperty(receiver);
4648 4646
4649 // TODO(verwaest): Encapsulate dictionary handling better. 4647 // TODO(verwaest): Encapsulate dictionary handling better.
4650 if (receiver->map()->is_dictionary_map()) { 4648 if (receiver->map()->is_dictionary_map()) {
4651 // TODO(verwaest): Probably should ensure this is done beforehand. 4649 // TODO(verwaest): Probably should ensure this is done beforehand.
4652 it->InternalizeName(); 4650 it->InternalizeName();
4653 // TODO(dcarney): just populate TransitionPropertyCell here? 4651 // TODO(dcarney): just populate TransitionPropertyCell here?
4654 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); 4652 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
4655 } else { 4653 } else {
4656 // Write the property value. 4654 // Write the property value.
4657 it->WriteDataValue(value); 4655 it->WriteDataValue(value);
(...skipping 5265 matching lines...) Expand 10 before | Expand all | Expand 10 after
9923 9921
9924 case ACCESSOR: 9922 case ACCESSOR:
9925 case ACCESSOR_CONSTANT: 9923 case ACCESSOR_CONSTANT:
9926 return false; 9924 return false;
9927 } 9925 }
9928 9926
9929 UNREACHABLE(); 9927 UNREACHABLE();
9930 return false; 9928 return false;
9931 } 9929 }
9932 9930
9931 namespace {
9932
9933 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
9934 Handle<Object> value) {
9935 if (map->instance_descriptors()->CanHoldValue(descriptor, *value)) return map;
9936
9937 Isolate* isolate = map->GetIsolate();
9938 PropertyAttributes attributes =
9939 map->instance_descriptors()->GetDetails(descriptor).attributes();
9940 Representation representation = value->OptimalRepresentation();
9941 Handle<FieldType> type = value->OptimalType(isolate, representation);
9942
9943 return Map::ReconfigureProperty(map, descriptor, kData, attributes,
9944 representation, type, FORCE_FIELD);
9945 }
9946
9947 } // namespace
9933 9948
9934 // static 9949 // static
9935 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor, 9950 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
9936 Handle<Object> value) { 9951 Handle<Object> value) {
9937 // Dictionaries can store any property value. 9952 // Dictionaries can store any property value.
9938 if (map->is_dictionary_map()) return map; 9953 if (map->is_dictionary_map()) return map;
9939 9954
9940 // Migrate to the newest map before storing the property. 9955 // Update to the newest map before storing the property.
9941 map = Update(map); 9956 return UpdateDescriptorForValue(Update(map), descriptor, value);
9942
9943 Handle<DescriptorArray> descriptors(map->instance_descriptors());
9944
9945 if (descriptors->CanHoldValue(descriptor, *value)) return map;
9946
9947 Isolate* isolate = map->GetIsolate();
9948 PropertyAttributes attributes =
9949 descriptors->GetDetails(descriptor).attributes();
9950 Representation representation = value->OptimalRepresentation();
9951 Handle<FieldType> type = value->OptimalType(isolate, representation);
9952
9953 return ReconfigureProperty(map, descriptor, kData, attributes, representation,
9954 type, FORCE_FIELD);
9955 } 9957 }
9956 9958
9957 9959
9958 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, 9960 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
9959 Handle<Object> value, 9961 Handle<Object> value,
9960 PropertyAttributes attributes, 9962 PropertyAttributes attributes,
9961 StoreFromKeyed store_mode) { 9963 StoreFromKeyed store_mode) {
9962 // Dictionary maps can always have additional data properties. 9964 // Dictionary maps can always have additional data properties.
9963 if (map->is_dictionary_map()) return map; 9965 if (map->is_dictionary_map()) return map;
9964 9966
9965 // Migrate to the newest map before storing the property. 9967 // Migrate to the newest map before storing the property.
9966 map = Update(map); 9968 map = Update(map);
9967 9969
9968 Map* maybe_transition = 9970 Map* maybe_transition =
9969 TransitionArray::SearchTransition(*map, kData, *name, attributes); 9971 TransitionArray::SearchTransition(*map, kData, *name, attributes);
9970 if (maybe_transition != NULL) { 9972 if (maybe_transition != NULL) {
9971 Handle<Map> transition(maybe_transition); 9973 Handle<Map> transition(maybe_transition);
9972 int descriptor = transition->LastAdded(); 9974 int descriptor = transition->LastAdded();
9973 9975
9974 DCHECK_EQ(attributes, transition->instance_descriptors() 9976 DCHECK_EQ(attributes, transition->instance_descriptors()
9975 ->GetDetails(descriptor) 9977 ->GetDetails(descriptor)
9976 .attributes()); 9978 .attributes());
9977 9979
9978 return Map::PrepareForDataProperty(transition, descriptor, value); 9980 return UpdateDescriptorForValue(transition, descriptor, value);
9979 } 9981 }
9980 9982
9981 TransitionFlag flag = INSERT_TRANSITION; 9983 TransitionFlag flag = INSERT_TRANSITION;
9982 MaybeHandle<Map> maybe_map; 9984 MaybeHandle<Map> maybe_map;
9983 if (value->IsJSFunction()) { 9985 if (value->IsJSFunction()) {
9984 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag); 9986 maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
9985 } else if (!map->TooManyFastProperties(store_mode)) { 9987 } else if (!map->TooManyFastProperties(store_mode)) {
9986 Isolate* isolate = name->GetIsolate(); 9988 Isolate* isolate = name->GetIsolate();
9987 Representation representation = value->OptimalRepresentation(); 9989 Representation representation = value->OptimalRepresentation();
9988 Handle<FieldType> type = value->OptimalType(isolate, representation); 9990 Handle<FieldType> type = value->OptimalType(isolate, representation);
(...skipping 9994 matching lines...) Expand 10 before | Expand all | Expand 10 after
19983 if (cell->value() != *new_value) { 19985 if (cell->value() != *new_value) {
19984 cell->set_value(*new_value); 19986 cell->set_value(*new_value);
19985 Isolate* isolate = cell->GetIsolate(); 19987 Isolate* isolate = cell->GetIsolate();
19986 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19988 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19987 isolate, DependentCode::kPropertyCellChangedGroup); 19989 isolate, DependentCode::kPropertyCellChangedGroup);
19988 } 19990 }
19989 } 19991 }
19990 19992
19991 } // namespace internal 19993 } // namespace internal
19992 } // namespace v8 19994 } // namespace v8
OLDNEW
« no previous file with comments | « src/lookup.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698