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

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: Created 5 years, 9 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
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 1858 matching lines...) Expand 10 before | Expand all | Expand 10 after
1869 } 1869 }
1870 1870
1871 1871
1872 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { 1872 void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) {
1873 Isolate* isolate = parent->GetIsolate(); 1873 Isolate* isolate = parent->GetIsolate();
1874 Handle<Name> name = isolate->factory()->elements_transition_symbol(); 1874 Handle<Name> name = isolate->factory()->elements_transition_symbol();
1875 ConnectTransition(parent, child, name, SPECIAL_TRANSITION); 1875 ConnectTransition(parent, child, name, SPECIAL_TRANSITION);
1876 } 1876 }
1877 1877
1878 1878
1879 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { 1879 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
1880 int expected_additional_properties) {
1880 if (object->map() == *new_map) return; 1881 if (object->map() == *new_map) return;
1882 Handle<Map> old_map(object->map());
1881 if (object->HasFastProperties()) { 1883 if (object->HasFastProperties()) {
1882 if (!new_map->is_dictionary_map()) { 1884 if (!new_map->is_dictionary_map()) {
1883 Handle<Map> old_map(object->map());
1884 MigrateFastToFast(object, new_map); 1885 MigrateFastToFast(object, new_map);
1885 if (old_map->is_prototype_map()) { 1886 if (old_map->is_prototype_map()) {
1886 // Clear out the old descriptor array to avoid problems to sharing 1887 // Clear out the old descriptor array to avoid problems to sharing
1887 // the descriptor array without using an explicit. 1888 // the descriptor array without using an explicit.
1888 old_map->InitializeDescriptors( 1889 old_map->InitializeDescriptors(
1889 old_map->GetHeap()->empty_descriptor_array(), 1890 old_map->GetHeap()->empty_descriptor_array(),
1890 LayoutDescriptor::FastPointerLayout()); 1891 LayoutDescriptor::FastPointerLayout());
1891 // Ensure that no transition was inserted for prototype migrations. 1892 // Ensure that no transition was inserted for prototype migrations.
1892 DCHECK_EQ(0, TransitionArray::NumberOfTransitions( 1893 DCHECK_EQ(0, TransitionArray::NumberOfTransitions(
1893 old_map->raw_transitions())); 1894 old_map->raw_transitions()));
1894 DCHECK(new_map->GetBackPointer()->IsUndefined()); 1895 DCHECK(new_map->GetBackPointer()->IsUndefined());
1895 } 1896 }
1896 } else { 1897 } else {
1897 MigrateFastToSlow(object, new_map, 0); 1898 MigrateFastToSlow(object, new_map, expected_additional_properties);
1898 } 1899 }
1899 } else { 1900 } else {
1900 // For slow-to-fast migrations JSObject::TransformToFastProperties() 1901 // For slow-to-fast migrations JSObject::MigrateSlowToFast()
1901 // must be used instead. 1902 // must be used instead.
1902 CHECK(new_map->is_dictionary_map()); 1903 CHECK(new_map->is_dictionary_map());
1903 1904
1904 // Slow-to-slow migration is trivial. 1905 // Slow-to-slow migration is trivial.
1905 object->set_map(*new_map); 1906 object->set_map(*new_map);
1906 } 1907 }
1908 if (old_map->is_prototype_map()) {
1909 new_map->set_prototype_info(old_map->prototype_info());
1910 old_map->set_prototype_info(Smi::FromInt(0));
1911 }
1907 } 1912 }
1908 1913
1909 1914
1910 // To migrate a fast instance to a fast map: 1915 // To migrate a fast instance to a fast map:
1911 // - First check whether the instance needs to be rewritten. If not, simply 1916 // - First check whether the instance needs to be rewritten. If not, simply
1912 // change the map. 1917 // change the map.
1913 // - Otherwise, allocate a fixed array large enough to hold all fields, in 1918 // - Otherwise, allocate a fixed array large enough to hold all fields, in
1914 // addition to unused space. 1919 // addition to unused space.
1915 // - Copy all existing properties in, in the following order: backing store 1920 // - Copy all existing properties in, in the following order: backing store
1916 // properties, unused fields, inobject properties. 1921 // properties, unused fields, inobject properties.
(...skipping 2567 matching lines...) Expand 10 before | Expand all | Expand 10 after
4484 4489
4485 void JSObject::NormalizeProperties(Handle<JSObject> object, 4490 void JSObject::NormalizeProperties(Handle<JSObject> object,
4486 PropertyNormalizationMode mode, 4491 PropertyNormalizationMode mode,
4487 int expected_additional_properties, 4492 int expected_additional_properties,
4488 const char* reason) { 4493 const char* reason) {
4489 if (!object->HasFastProperties()) return; 4494 if (!object->HasFastProperties()) return;
4490 4495
4491 Handle<Map> map(object->map()); 4496 Handle<Map> map(object->map());
4492 Handle<Map> new_map = Map::Normalize(map, mode, reason); 4497 Handle<Map> new_map = Map::Normalize(map, mode, reason);
4493 4498
4494 MigrateFastToSlow(object, new_map, expected_additional_properties); 4499 MigrateToMap(object, new_map, expected_additional_properties);
Jakob Kummerow 2015/03/24 10:40:13 MigrateToMap is now *the* choke point for changing
4495 } 4500 }
4496 4501
4497 4502
4498 void JSObject::MigrateFastToSlow(Handle<JSObject> object, 4503 void JSObject::MigrateFastToSlow(Handle<JSObject> object,
4499 Handle<Map> new_map, 4504 Handle<Map> new_map,
4500 int expected_additional_properties) { 4505 int expected_additional_properties) {
4501 // The global object is always normalized. 4506 // The global object is always normalized.
4502 DCHECK(!object->IsGlobalObject()); 4507 DCHECK(!object->IsGlobalObject());
4503 // JSGlobalProxy must never be normalized 4508 // JSGlobalProxy must never be normalized
4504 DCHECK(!object->IsJSGlobalProxy()); 4509 DCHECK(!object->IsJSGlobalProxy());
(...skipping 5354 matching lines...) Expand 10 before | Expand all | Expand 10 after
9859 if (details.representation().IsHeapObject() || 9864 if (details.representation().IsHeapObject() ||
9860 details.representation().IsTagged()) { 9865 details.representation().IsTagged()) {
9861 FieldIndex index = FieldIndex::ForDescriptor(map, i); 9866 FieldIndex index = FieldIndex::ForDescriptor(map, i);
9862 if (object->RawFastPropertyAt(index)->IsJSFunction()) return true; 9867 if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
9863 } 9868 }
9864 } 9869 }
9865 return false; 9870 return false;
9866 } 9871 }
9867 9872
9868 9873
9874 // static
9869 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, 9875 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
9870 PrototypeOptimizationMode mode) { 9876 PrototypeOptimizationMode mode) {
9871 if (object->IsGlobalObject()) return; 9877 if (object->IsGlobalObject()) return;
9872 if (object->IsJSGlobalProxy()) return; 9878 if (object->IsJSGlobalProxy()) return;
9873 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) { 9879 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
9874 // First normalize to ensure all JSFunctions are DATA_CONSTANT. 9880 // First normalize to ensure all JSFunctions are DATA_CONSTANT.
9875 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, 9881 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
9876 "NormalizeAsPrototype"); 9882 "NormalizeAsPrototype");
9877 } 9883 }
9878 bool has_just_copied_map = false; 9884 Handle<Map> previous_map(object->map());
9879 if (!object->HasFastProperties()) { 9885 if (!object->HasFastProperties()) {
9880 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); 9886 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
9881 has_just_copied_map = true;
9882 } 9887 }
9883 if (mode == FAST_PROTOTYPE && object->HasFastProperties() && 9888 if (!object->map()->is_prototype_map()) {
9884 !object->map()->is_prototype_map()) { 9889 if (object->map() == *previous_map) {
9885 if (!has_just_copied_map) {
9886 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype"); 9890 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
9887 JSObject::MigrateToMap(object, new_map); 9891 JSObject::MigrateToMap(object, new_map);
9888 } 9892 }
9889 Object* maybe_constructor = object->map()->GetConstructor(); 9893 Object* maybe_constructor = object->map()->GetConstructor();
9890 if (maybe_constructor->IsJSFunction()) { 9894 if (maybe_constructor->IsJSFunction()) {
9891 JSFunction* constructor = JSFunction::cast(maybe_constructor); 9895 JSFunction* constructor = JSFunction::cast(maybe_constructor);
9892 // Replace the pointer to the exact constructor with the Object function 9896 // Replace the pointer to the exact constructor with the Object function
9893 // from the same context if undetectable from JS. This is to avoid keeping 9897 // from the same context if undetectable from JS. This is to avoid keeping
9894 // memory alive unnecessarily. 9898 // memory alive unnecessarily.
9895 if (!constructor->shared()->IsApiFunction() && 9899 if (!constructor->shared()->IsApiFunction() &&
9896 object->class_name() == 9900 object->class_name() ==
9897 object->GetIsolate()->heap()->Object_string()) { 9901 object->GetIsolate()->heap()->Object_string()) {
9898 Context* context = constructor->context()->native_context(); 9902 Context* context = constructor->context()->native_context();
9899 JSFunction* object_function = context->object_function(); 9903 JSFunction* object_function = context->object_function();
9900 object->map()->SetConstructor(object_function); 9904 object->map()->SetConstructor(object_function);
9901 } 9905 }
9902 } 9906 }
9903 object->map()->set_is_prototype_map(true); 9907 object->map()->set_is_prototype_map(true);
9904 } 9908 }
9905 } 9909 }
9906 9910
9907 9911
9912 // static
9908 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 9913 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
9909 if (!object->map()->is_prototype_map()) return; 9914 if (!object->map()->is_prototype_map()) return;
9910 OptimizeAsPrototype(object, FAST_PROTOTYPE); 9915 OptimizeAsPrototype(object, FAST_PROTOTYPE);
9911 } 9916 }
9912 9917
9913 9918
9919 // static
9914 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype, 9920 void JSObject::RegisterPrototypeUser(Handle<JSObject> prototype,
9915 Handle<HeapObject> user) { 9921 Handle<HeapObject> user) {
9916 DCHECK(FLAG_track_prototype_users); 9922 DCHECK(FLAG_track_prototype_users);
9917 Isolate* isolate = prototype->GetIsolate(); 9923 Isolate* isolate = prototype->GetIsolate();
9918 Handle<Name> symbol = isolate->factory()->prototype_users_symbol(); 9924 if (prototype->IsJSGlobalProxy()) {
9919 9925 prototype = handle(JSObject::cast(prototype->map()->prototype()), isolate);
9920 // Get prototype users array, create it if it doesn't exist yet. 9926 }
9921 Handle<Object> maybe_array = 9927 Handle<PrototypeInfo> proto_info;
9922 JSObject::GetProperty(prototype, symbol).ToHandleChecked(); 9928 Object* maybe_proto_info = prototype->map()->prototype_info();
9923 9929 if (maybe_proto_info->IsPrototypeInfo()) {
9924 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_array, user); 9930 proto_info = handle(PrototypeInfo::cast(maybe_proto_info), isolate);
9925 if (!maybe_array.is_identical_to(new_array)) { 9931 } else {
9926 JSObject::SetOwnPropertyIgnoreAttributes(prototype, symbol, new_array, 9932 proto_info = isolate->factory()->NewPrototypeInfo(prototype);
9927 DONT_ENUM).Assert(); 9933 prototype->map()->set_prototype_info(*proto_info);
9934 }
9935 Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
9936 Handle<WeakFixedArray> new_array = WeakFixedArray::Add(maybe_registry, user);
9937 if (!maybe_registry.is_identical_to(new_array)) {
9938 proto_info->set_prototype_users(*new_array);
9928 } 9939 }
9929 } 9940 }
9930 9941
9931 9942
9943 // static
9932 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype, 9944 void JSObject::UnregisterPrototypeUser(Handle<JSObject> prototype,
9933 Handle<HeapObject> user) { 9945 Handle<HeapObject> user) {
9934 Isolate* isolate = prototype->GetIsolate(); 9946 Isolate* isolate = prototype->GetIsolate();
9935 Handle<Name> symbol = isolate->factory()->prototype_users_symbol(); 9947 if (prototype->IsJSGlobalProxy()) {
9936 9948 prototype = handle(JSObject::cast(prototype->map()->prototype()), isolate);
9937 Handle<Object> maybe_array = 9949 }
9938 JSObject::GetProperty(prototype, symbol).ToHandleChecked(); 9950 DCHECK(prototype->map()->is_prototype_map());
9939 if (!maybe_array->IsWeakFixedArray()) return; 9951 Object* maybe_proto_info = prototype->map()->prototype_info();
9940 Handle<WeakFixedArray>::cast(maybe_array)->Remove(user); 9952 if (!maybe_proto_info->IsPrototypeInfo()) return;
9953 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
9954 isolate);
9955 Object* maybe_registry = proto_info->prototype_users();
9956 if (!maybe_registry->IsWeakFixedArray()) return;
9957 WeakFixedArray::cast(maybe_registry)->Remove(user);
9941 } 9958 }
9942 9959
9943 9960
9944 void Map::SetPrototype(Handle<Object> prototype, 9961 void Map::SetPrototype(Handle<Object> prototype,
9945 PrototypeOptimizationMode proto_mode) { 9962 PrototypeOptimizationMode proto_mode) {
9946 if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) { 9963 if (this->prototype()->IsJSObject() && FLAG_track_prototype_users) {
9947 Handle<JSObject> old_prototype(JSObject::cast(this->prototype())); 9964 Handle<JSObject> old_prototype(JSObject::cast(this->prototype()));
9948 JSObject::UnregisterPrototypeUser(old_prototype, handle(this)); 9965 JSObject::UnregisterPrototypeUser(old_prototype, handle(this));
9949 } 9966 }
9950 if (prototype->IsJSObject()) { 9967 if (prototype->IsJSObject()) {
9951 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); 9968 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
9952 if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) { 9969 if (ShouldRegisterAsPrototypeUser(prototype_jsobj)) {
9953 JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this)); 9970 JSObject::RegisterPrototypeUser(prototype_jsobj, handle(this));
9954 } 9971 }
9955 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode); 9972 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
9956 } 9973 }
9957 WriteBarrierMode wb_mode = 9974 WriteBarrierMode wb_mode =
9958 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; 9975 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
9959 set_prototype(*prototype, wb_mode); 9976 set_prototype(*prototype, wb_mode);
9960 } 9977 }
9961 9978
9962 9979
9963 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) { 9980 bool Map::ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype) {
9964 if (!FLAG_track_prototype_users) return false; 9981 if (!FLAG_track_prototype_users) return false;
9965 if (this->is_prototype_map()) return true; 9982 if (this->is_prototype_map()) return true;
9966 if (this->is_dictionary_map()) return false;
9967 Object* back = GetBackPointer(); 9983 Object* back = GetBackPointer();
9968 if (!back->IsMap()) return true; 9984 if (!back->IsMap()) return true;
9969 if (Map::cast(back)->prototype() != *prototype) return true; 9985 if (Map::cast(back)->prototype() != *prototype) return true;
9970 return false; 9986 return false;
9971 } 9987 }
9972 9988
9973 9989
9974 bool Map::CanUseOptimizationsBasedOnPrototypeRegistry() {
9975 if (!FLAG_track_prototype_users) return false;
9976 if (this->is_prototype_map()) return true;
9977 if (GetBackPointer()->IsMap()) return true;
9978 return false;
9979 }
9980
9981
9982 Handle<Object> CacheInitialJSArrayMaps( 9990 Handle<Object> CacheInitialJSArrayMaps(
9983 Handle<Context> native_context, Handle<Map> initial_map) { 9991 Handle<Context> native_context, Handle<Map> initial_map) {
9984 // Replace all of the cached initial array maps in the native context with 9992 // Replace all of the cached initial array maps in the native context with
9985 // the appropriate transitioned elements kind maps. 9993 // the appropriate transitioned elements kind maps.
9986 Factory* factory = native_context->GetIsolate()->factory(); 9994 Factory* factory = native_context->GetIsolate()->factory();
9987 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles( 9995 Handle<FixedArray> maps = factory->NewFixedArrayWithHoles(
9988 kElementsKindCount, TENURED); 9996 kElementsKindCount, TENURED);
9989 9997
9990 Handle<Map> current_map = initial_map; 9998 Handle<Map> current_map = initial_map;
9991 ElementsKind kind = current_map->elements_kind(); 9999 ElementsKind kind = current_map->elements_kind();
(...skipping 7087 matching lines...) Expand 10 before | Expand all | Expand 10 after
17079 CompilationInfo* info) { 17087 CompilationInfo* info) {
17080 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( 17088 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
17081 handle(cell->dependent_code(), info->isolate()), 17089 handle(cell->dependent_code(), info->isolate()),
17082 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); 17090 DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
17083 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); 17091 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
17084 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( 17092 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
17085 cell, info->zone()); 17093 cell, info->zone());
17086 } 17094 }
17087 17095
17088 } } // namespace v8::internal 17096 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698