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

Side by Side Diff: src/objects.cc

Issue 1033653002: Move prototype metadata from internal properties to prototype maps (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: small fixes Created 5 years, 8 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/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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 <iomanip> 5 #include <iomanip>
6 #include <sstream> 6 #include <sstream>
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/accessors.h" 10 #include "src/accessors.h"
(...skipping 1867 matching lines...) Expand 10 before | Expand all | Expand 10 after
1878 } 1878 }
1879 1879
1880 1880
1881 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { 1881 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
1882 Isolate* isolate = parent->GetIsolate(); 1882 Isolate* isolate = parent->GetIsolate();
1883 Handle<Name> name = isolate->factory()->elements_transition_symbol(); 1883 Handle<Name> name = isolate->factory()->elements_transition_symbol();
1884 ConnectTransition(parent, child, name, SPECIAL_TRANSITION); 1884 ConnectTransition(parent, child, name, SPECIAL_TRANSITION);
1885 } 1885 }
1886 1886
1887 1887
1888 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { 1888 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
1889 int expected_additional_properties) {
1889 if (object->map() == *new_map) return; 1890 if (object->map() == *new_map) return;
1891 Handle<Map> old_map(object->map());
1890 if (object->HasFastProperties()) { 1892 if (object->HasFastProperties()) {
1891 if (!new_map->is_dictionary_map()) { 1893 if (!new_map->is_dictionary_map()) {
1892 Handle<Map> old_map(object->map());
1893 MigrateFastToFast(object, new_map); 1894 MigrateFastToFast(object, new_map);
1894 if (old_map->is_prototype_map()) { 1895 if (old_map->is_prototype_map()) {
1895 // Clear out the old descriptor array to avoid problems to sharing 1896 // Clear out the old descriptor array to avoid problems to sharing
1896 // the descriptor array without using an explicit. 1897 // the descriptor array without using an explicit.
1897 old_map->InitializeDescriptors( 1898 old_map->InitializeDescriptors(
1898 old_map->GetHeap()->empty_descriptor_array(), 1899 old_map->GetHeap()->empty_descriptor_array(),
1899 LayoutDescriptor::FastPointerLayout()); 1900 LayoutDescriptor::FastPointerLayout());
1900 // Ensure that no transition was inserted for prototype migrations. 1901 // Ensure that no transition was inserted for prototype migrations.
1901 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( 1902 DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1902 old_map->raw_transitions())); 1903 old_map->raw_transitions()));
1903 DCHECK(new_map->GetBackPointer()->IsUndefined()); 1904 DCHECK(new_map->GetBackPointer()->IsUndefined());
1904 } 1905 }
1905 } else { 1906 } else {
1906 MigrateFastToSlow(object, new_map, 0); 1907 MigrateFastToSlow(object, new_map, expected_additional_properties);
1907 } 1908 }
1908 } else { 1909 } else {
1909 // For slow-to-fast migrations JSObject::TransformToFastProperties() 1910 // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1910 // must be used instead. 1911 // must be used instead.
1911 CHECK(new_map->is_dictionary_map()); 1912 CHECK(new_map->is_dictionary_map());
1912 1913
1913 // Slow-to-slow migration is trivial. 1914 // Slow-to-slow migration is trivial.
1914 object->set_map(*new_map); 1915 object->set_map(*new_map);
1915 } 1916 }
1917 if (old_map->is_prototype_map()) {
1918 new_map->set_prototype_info(old_map->prototype_info());
1919 old_map->set_prototype_info(Smi::FromInt(0));
1920 }
1916 } 1921 }
1917 1922
1918 1923
1919 // To migrate a fast instance to a fast map: 1924 // To migrate a fast instance to a fast map:
1920 // - First check whether the instance needs to be rewritten. If not, simply 1925 // - First check whether the instance needs to be rewritten. If not, simply
1921 // change the map. 1926 // change the map.
1922 // - Otherwise, allocate a fixed array large enough to hold all fields, in 1927 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1923 // addition to unused space. 1928 // addition to unused space.
1924 // - Copy all existing properties in, in the following order: backing store 1929 // - Copy all existing properties in, in the following order: backing store
1925 // properties, unused fields, inobject properties. 1930 // properties, unused fields, inobject properties.
(...skipping 2582 matching lines...) Expand 10 before | Expand all | Expand 10 after
4508 4513
4509 void JSObject::NormalizeProperties(Handle<JSObject> object, 4514 void JSObject::NormalizeProperties(Handle<JSObject> object,
4510 PropertyNormalizationMode mode, 4515 PropertyNormalizationMode mode,
4511 int expected_additional_properties, 4516 int expected_additional_properties,
4512 const char* reason) { 4517 const char* reason) {
4513 if (!object->HasFastProperties()) return; 4518 if (!object->HasFastProperties()) return;
4514 4519
4515 Handle<Map> map(object->map()); 4520 Handle<Map> map(object->map());
4516 Handle<Map> new_map = Map::Normalize(map, mode, reason); 4521 Handle<Map> new_map = Map::Normalize(map, mode, reason);
4517 4522
4518 MigrateFastToSlow(object, new_map, expected_additional_properties); 4523 MigrateToMap(object, new_map, expected_additional_properties);
4519 } 4524 }
4520 4525
4521 4526
4522 void JSObject::MigrateFastToSlow(Handle<JSObject> object, 4527 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4523 Handle<Map> new_map, 4528 Handle<Map> new_map,
4524 int expected_additional_properties) { 4529 int expected_additional_properties) {
4525 // The global object is always normalized. 4530 // The global object is always normalized.
4526 DCHECK(!object->IsGlobalObject()); 4531 DCHECK(!object->IsGlobalObject());
4527 // JSGlobalProxy must never be normalized 4532 // JSGlobalProxy must never be normalized
4528 DCHECK(!object->IsJSGlobalProxy()); 4533 DCHECK(!object->IsJSGlobalProxy());
(...skipping 5352 matching lines...) Expand 10 before | Expand all | Expand 10 after
9881 if (details.representation().IsHeapObject() || 9886 if (details.representation().IsHeapObject() ||
9882 details.representation().IsTagged()) { 9887 details.representation().IsTagged()) {
9883 FieldIndex index = FieldIndex::ForDescriptor(map, i); 9888 FieldIndex index = FieldIndex::ForDescriptor(map, i);
9884 if (object->RawFastPropertyAt(index)->IsJSFunction()) return true; 9889 if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
9885 } 9890 }
9886 } 9891 }
9887 return false; 9892 return false;
9888 } 9893 }
9889 9894
9890 9895
9896 // static
9891 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, 9897 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9892 PrototypeOptimizationMode mode) { 9898 PrototypeOptimizationMode mode) {
9893 if (object->IsGlobalObject()) return; 9899 if (object->IsGlobalObject()) return;
9894 if (object->IsJSGlobalProxy()) return; 9900 if (object->IsJSGlobalProxy()) return;
9895 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) { 9901 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
9896 // First normalize to ensure all JSFunctions are DATA_CONSTANT. 9902 // First normalize to ensure all JSFunctions are DATA_CONSTANT.
9897 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, 9903 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
9898 "NormalizeAsPrototype"); 9904 "NormalizeAsPrototype");
9899 } 9905 }
9900 bool has_just_copied_map = false; 9906 Handle<Map> previous_map(object->map());
9901 if (!object->HasFastProperties()) { 9907 if (!object->HasFastProperties()) {
9902 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); 9908 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
9903 has_just_copied_map = true;
9904 } 9909 }
9905 if (mode == FAST_PROTOTYPE && object->HasFastProperties() && 9910 if (!object->map()->is_prototype_map()) {
9906 !object->map()->is_prototype_map()) { 9911 if (object->map() == *previous_map) {
9907 if (!has_just_copied_map) {
9908 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype"); 9912 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
9909 JSObject::MigrateToMap(object, new_map); 9913 JSObject::MigrateToMap(object, new_map);
9910 } 9914 }
9911 Object* maybe_constructor = object->map()->GetConstructor(); 9915 Object* maybe_constructor = object->map()->GetConstructor();
9912 if (maybe_constructor->IsJSFunction()) { 9916 if (maybe_constructor->IsJSFunction()) {
9913 JSFunction* constructor = JSFunction::cast(maybe_constructor); 9917 JSFunction* constructor = JSFunction::cast(maybe_constructor);
9914 // Replace the pointer to the exact constructor with the Object function 9918 // Replace the pointer to the exact constructor with the Object function
9915 // from the same context if undetectable from JS. This is to avoid keeping 9919 // from the same context if undetectable from JS. This is to avoid keeping
9916 // memory alive unnecessarily. 9920 // memory alive unnecessarily.
9917 if (!constructor->shared()->IsApiFunction() && 9921 if (!constructor->shared()->IsApiFunction() &&
9918 object->class_name() == 9922 object->class_name() ==
9919 object->GetIsolate()->heap()->Object_string()) { 9923 object->GetIsolate()->heap()->Object_string()) {
9920 Context* context = constructor->context()->native_context(); 9924 Context* context = constructor->context()->native_context();
9921 JSFunction* object_function = context->object_function(); 9925 JSFunction* object_function = context->object_function();
9922 object->map()->SetConstructor(object_function); 9926 object->map()->SetConstructor(object_function);
9923 } 9927 }
9924 } 9928 }
9925 object->map()->set_is_prototype_map(true); 9929 object->map()->set_is_prototype_map(true);
9926 } 9930 }
9927 } 9931 }
9928 9932
9929 9933
9934 // static
9930 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 9935 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9931 if (!object->map()->is_prototype_map()) return; 9936 if (!object->map()->is_prototype_map()) return;
9932 OptimizeAsPrototype(object, FAST_PROTOTYPE); 9937 OptimizeAsPrototype(object, FAST_PROTOTYPE);
9933 } 9938 }
9934 9939
9935 9940
9941 // static
9936 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype, 9942 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
9937 Handle<HeapObject> user) { 9943 Handle<HeapObject> user) {
9938 DCHECK(FLAG_track_prototype_users); 9944 DCHECK(FLAG_track_prototype_users);
9939 Isolate* isolate = prototype->GetIsolate(); 9945 Isolate* isolate = prototype->GetIsolate();
9940 Handle<Name> symbol = isolate->factory()->prototype_users_symbol(); 9946 if (prototype->IsJSGlobalProxy()) {
9941 9947 PrototypeIterator iter(isolate, prototype);
9942 // Get prototype users array, create it if it doesn't exist yet. 9948 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9943 Handle<Object> maybe_array = 9949 }
9944 JSObject::GetProperty(prototype, symbol).ToHandleChecked(); 9950 Handle<PrototypeInfo> proto_info;
9945 9951 Object* maybe_proto_info = prototype->map()->prototype_info();
9946 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_array, user); 9952 if (maybe_proto_info->IsPrototypeInfo()) {
9947 if (!maybe_array.is_identical_to(new_array)) { 9953 proto_info = handle(PrototypeInfo::cast(maybe_proto_info), isolate);
9948 JSObject::SetOwnPropertyIgnoreAttributes(prototype, symbol, new_array, 9954 } else {
9949 DONT_ENUM).Assert(); 9955 proto_info = isolate->factory()->NewPrototypeInfo();
9956 prototype->map()->set_prototype_info(*proto_info);
9957 }
9958 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
9959 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_registry, user);
9960 if (!maybe_registry.is_identical_to(new_array)) {
9961 proto_info->set_prototype_users(*new_array);
9950 } 9962 }
9951 } 9963 }
9952 9964
9953 9965
9966 // static
9954 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype, 9967 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9955 Handle<HeapObject> user) { 9968 Handle<HeapObject> user) {
9956 Isolate* isolate = prototype->GetIsolate(); 9969 Isolate* isolate = prototype->GetIsolate();
9957 Handle<Name> symbol = isolate->factory()->prototype_users_symbol(); 9970 if (prototype->IsJSGlobalProxy()) {
9958 9971 PrototypeIterator iter(isolate, prototype);
9959 Handle<Object> maybe_array = 9972 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
9960 JSObject::GetProperty(prototype, symbol).ToHandleChecked(); 9973 }
9961 if (!maybe_array->IsWeakFixedArray()) return; 9974 DCHECK(prototype->map()->is_prototype_map());
9962 Handle<WeakFixedArray>::cast(maybe_array)->Remove(user); 9975 Object* maybe_proto_info = prototype->map()->prototype_info();
9976 if (!maybe_proto_info->IsPrototypeInfo()) return;
9977 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
9978 isolate);
9979 Object* maybe_registry = proto_info->prototype_users();
9980 if (!maybe_registry->IsWeakFixedArray()) return;
9981 WeakFixedArray::cast(maybe_registry)->Remove(user);
9963 } 9982 }
9964 9983
9965 9984
9966 void Map::SetPrototype(Handle<Object> prototype, 9985 void Map::SetPrototype(Handle<Object> prototype,
9967 PrototypeOptimizationMode proto_mode) { 9986 PrototypeOptimizationMode proto_mode) {
9968 if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) { 9987 if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
9969 Handle<JSObject> old_prototype(JSObject::cast(this->prototype())); 9988 Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
9970 JSObject::UnregisterPrototypeUser(old_prototype, handle(this)); 9989 JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
9971 } 9990 }
9972 if (prototype->IsJSObject()) { 9991 if (prototype->IsJSObject()) {
9973 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); 9992 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9974 if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) { 9993 if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
9975 JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this)); 9994 JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
9976 } 9995 }
9977 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode); 9996 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9978 } 9997 }
9979 WriteBarrierMode wb_mode = 9998 WriteBarrierMode wb_mode =
9980 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; 9999 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9981 set_prototype(*prototype, wb_mode); 10000 set_prototype(*prototype, wb_mode);
9982 } 10001 }
9983 10002
9984 10003
9985 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) { 10004 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
9986 if (!FLAG_track_prototype_users) return false; 10005 if (!FLAG_track_prototype_users) return false;
9987 if (this->is_prototype_map()) return true; 10006 if (this->is_prototype_map()) return true;
9988 if (this->is_dictionary_map()) return false;
9989 Object* back = GetBackPointer(); 10007 Object* back = GetBackPointer();
9990 if (!back->IsMap()) return true; 10008 if (!back->IsMap()) return true;
9991 if (Map::cast(back)->prototype() != *prototype) return true; 10009 if (Map::cast(back)->prototype() != *prototype) return true;
9992 return false; 10010 return false;
9993 } 10011 }
9994 10012
9995 10013
9996 bool Map::CanUseOptimizationsBasedOnPrototypeRegistry() {
9997 if (!FLAG_track_prototype_users) return false;
9998 if (this->is_prototype_map()) return true;
9999 if (GetBackPointer()->IsMap()) return true;
10000 return false;
10001 }
10002
10003
10004 Handle<Object> CacheInitialJSArrayMaps( 10014 Handle<Object> CacheInitialJSArrayMaps(
10005 Handle<Context> native_context, Handle<Map> initial_map) { 10015 Handle<Context> native_context, Handle<Map> initial_map) {
10006 // Replace all of the cached initial array maps in the native context with 10016 // Replace all of the cached initial array maps in the native context with
10007 // the appropriate transitioned elements kind maps. 10017 // the appropriate transitioned elements kind maps.
10008 Factory* factory = native_context->GetIsolate()->factory(); 10018 Factory* factory = native_context->GetIsolate()->factory();
10009 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 10019 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
10010 kElementsKindCount, TENURED); 10020 kElementsKindCount, TENURED);
10011 10021
10012 Handle<Map> current_map = initial_map; 10022 Handle<Map> current_map = initial_map;
10013 ElementsKind kind = current_map->elements_kind(); 10023 ElementsKind kind = current_map->elements_kind();
(...skipping 7092 matching lines...) Expand 10 before | Expand all | Expand 10 after
17106 CompilationInfo* info) { 17116 CompilationInfo* info) {
17107 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( 17117 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
17108 handle(cell->dependent_code(), info->isolate()), 17118 handle(cell->dependent_code(), info->isolate()),
17109 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); 17119 DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
17110 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 17120 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17111 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 17121 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17112 cell, info->zone()); 17122 cell, info->zone());
17113 } 17123 }
17114 17124
17115 } } // namespace v8::internal 17125 } } // namespace v8::internal
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