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

Side by Side Diff: src/objects.cc

Issue 2036493006: Keep prototype maps in dictionary mode until ICs see them (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: make ignition tests happy Created 4 years, 6 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-inl.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 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 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate, 1019 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
1020 Object* receiver) { 1020 Object* receiver) {
1021 // API calls are only supported with JSObject receivers. 1021 // API calls are only supported with JSObject receivers.
1022 if (!receiver->IsJSObject()) return isolate->heap()->null_value(); 1022 if (!receiver->IsJSObject()) return isolate->heap()->null_value();
1023 Object* recv_type = this->signature(); 1023 Object* recv_type = this->signature();
1024 // No signature, return holder. 1024 // No signature, return holder.
1025 if (recv_type->IsUndefined(isolate)) return receiver; 1025 if (recv_type->IsUndefined(isolate)) return receiver;
1026 FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type); 1026 FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
1027 // Check the receiver. 1027 // Check the receiver.
1028 for (PrototypeIterator iter(isolate, JSObject::cast(receiver), 1028 for (PrototypeIterator iter(isolate, JSObject::cast(receiver),
1029 PrototypeIterator::START_AT_RECEIVER, 1029 kStartAtReceiver,
1030 PrototypeIterator::END_AT_NON_HIDDEN); 1030 PrototypeIterator::END_AT_NON_HIDDEN);
1031 !iter.IsAtEnd(); iter.Advance()) { 1031 !iter.IsAtEnd(); iter.Advance()) {
1032 if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent(); 1032 if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
1033 } 1033 }
1034 return isolate->heap()->null_value(); 1034 return isolate->heap()->null_value();
1035 } 1035 }
1036 1036
1037 1037
1038 // static 1038 // static
1039 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor, 1039 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 details = details.set_index(enumeration_index); 1477 details = details.set_index(enumeration_index);
1478 property_dictionary->SetEntry(entry, name, value, details); 1478 property_dictionary->SetEntry(entry, name, value, details);
1479 } 1479 }
1480 } 1480 }
1481 } 1481 }
1482 1482
1483 // static 1483 // static
1484 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate, 1484 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
1485 Handle<JSReceiver> object, 1485 Handle<JSReceiver> object,
1486 Handle<Object> proto) { 1486 Handle<Object> proto) {
1487 PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER); 1487 PrototypeIterator iter(isolate, object, kStartAtReceiver);
1488 while (true) { 1488 while (true) {
1489 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); 1489 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
1490 if (iter.IsAtEnd()) return Just(false); 1490 if (iter.IsAtEnd()) return Just(false);
1491 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) { 1491 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
1492 return Just(true); 1492 return Just(true);
1493 } 1493 }
1494 } 1494 }
1495 } 1495 }
1496 1496
1497 Map* Object::GetRootMap(Isolate* isolate) { 1497 Map* Object::GetRootMap(Isolate* isolate) {
(...skipping 10357 matching lines...) Expand 10 before | Expand all | Expand 10 after
11855 if (details.location() == kDescriptor) continue; 11855 if (details.location() == kDescriptor) continue;
11856 if (details.representation().IsHeapObject() || 11856 if (details.representation().IsHeapObject() ||
11857 details.representation().IsTagged()) { 11857 details.representation().IsTagged()) {
11858 FieldIndex index = FieldIndex::ForDescriptor(map, i); 11858 FieldIndex index = FieldIndex::ForDescriptor(map, i);
11859 if (object->RawFastPropertyAt(index)->IsJSFunction()) return true; 11859 if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
11860 } 11860 }
11861 } 11861 }
11862 return false; 11862 return false;
11863 } 11863 }
11864 11864
11865 // static
11866 void JSObject::MakePrototypesFast(Handle<Object> receiver,
11867 WhereToStart where_to_start,
11868 Isolate* isolate) {
11869 if (!receiver->IsJSReceiver()) return;
11870 for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
11871 where_to_start);
11872 !iter.IsAtEnd(); iter.Advance()) {
11873 Handle<Object> current = PrototypeIterator::GetCurrent(iter);
11874 if (!current->IsJSObject()) return;
11875 Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
11876 Map* current_map = current_obj->map();
11877 if (current_map->is_prototype_map() &&
11878 !current_map->should_be_fast_prototype_map()) {
11879 Handle<Map> map(current_map);
11880 Map::SetShouldBeFastPrototypeMap(map, true, isolate);
11881 JSObject::OptimizeAsPrototype(current_obj, FAST_PROTOTYPE);
11882 }
11883 }
11884 }
11865 11885
11866 // static 11886 // static
11867 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, 11887 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
11868 PrototypeOptimizationMode mode) { 11888 PrototypeOptimizationMode mode) {
11869 if (object->IsJSGlobalObject()) return; 11889 if (object->IsJSGlobalObject()) return;
11870 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) { 11890 if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
11871 // First normalize to ensure all JSFunctions are DATA_CONSTANT. 11891 // First normalize to ensure all JSFunctions are DATA_CONSTANT.
11872 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, 11892 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
11873 "NormalizeAsPrototype"); 11893 "NormalizeAsPrototype");
11874 } 11894 }
11875 Handle<Map> previous_map(object->map()); 11895 Handle<Map> previous_map(object->map());
11876 if (!object->HasFastProperties()) { 11896 if (object->map()->is_prototype_map()) {
11877 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); 11897 if (object->map()->should_be_fast_prototype_map() &&
11878 } 11898 !object->HasFastProperties()) {
11879 if (!object->map()->is_prototype_map()) { 11899 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
11900 }
11901 } else {
11880 if (object->map() == *previous_map) { 11902 if (object->map() == *previous_map) {
11881 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype"); 11903 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
11882 JSObject::MigrateToMap(object, new_map); 11904 JSObject::MigrateToMap(object, new_map);
11883 } 11905 }
11884 object->map()->set_is_prototype_map(true); 11906 object->map()->set_is_prototype_map(true);
11885 11907
11886 // Replace the pointer to the exact constructor with the Object function 11908 // Replace the pointer to the exact constructor with the Object function
11887 // from the same context if undetectable from JS. This is to avoid keeping 11909 // from the same context if undetectable from JS. This is to avoid keeping
11888 // memory alive unnecessarily. 11910 // memory alive unnecessarily.
11889 Object* maybe_constructor = object->map()->GetConstructor(); 11911 Object* maybe_constructor = object->map()->GetConstructor();
11890 if (maybe_constructor->IsJSFunction()) { 11912 if (maybe_constructor->IsJSFunction()) {
11891 JSFunction* constructor = JSFunction::cast(maybe_constructor); 11913 JSFunction* constructor = JSFunction::cast(maybe_constructor);
11892 Isolate* isolate = object->GetIsolate(); 11914 Isolate* isolate = object->GetIsolate();
11893 if (!constructor->shared()->IsApiFunction() && 11915 if (!constructor->shared()->IsApiFunction() &&
11894 object->class_name() == isolate->heap()->Object_string()) { 11916 object->class_name() == isolate->heap()->Object_string()) {
11895 Context* context = constructor->context()->native_context(); 11917 Context* context = constructor->context()->native_context();
11896 JSFunction* object_function = context->object_function(); 11918 JSFunction* object_function = context->object_function();
11897 object->map()->SetConstructor(object_function); 11919 object->map()->SetConstructor(object_function);
11898 } 11920 }
11899 } 11921 }
11900 } 11922 }
11901 } 11923 }
11902 11924
11903 11925
11904 // static 11926 // static
11905 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { 11927 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
11906 if (!object->map()->is_prototype_map()) return; 11928 if (!object->map()->is_prototype_map()) return;
11929 if (!object->map()->should_be_fast_prototype_map()) return;
11907 OptimizeAsPrototype(object, FAST_PROTOTYPE); 11930 OptimizeAsPrototype(object, FAST_PROTOTYPE);
11908 } 11931 }
11909 11932
11910 11933
11911 // static 11934 // static
11912 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) { 11935 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
11913 // Contract: In line with InvalidatePrototypeChains()'s requirements, 11936 // Contract: In line with InvalidatePrototypeChains()'s requirements,
11914 // leaf maps don't need to register as users, only prototypes do. 11937 // leaf maps don't need to register as users, only prototypes do.
11915 DCHECK(user->is_prototype_map()); 11938 DCHECK(user->is_prototype_map());
11916 11939
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
12038 Isolate* isolate) { 12061 Isolate* isolate) {
12039 Object* maybe_proto_info = prototype_map->prototype_info(); 12062 Object* maybe_proto_info = prototype_map->prototype_info();
12040 if (maybe_proto_info->IsPrototypeInfo()) { 12063 if (maybe_proto_info->IsPrototypeInfo()) {
12041 return handle(PrototypeInfo::cast(maybe_proto_info), isolate); 12064 return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
12042 } 12065 }
12043 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo(); 12066 Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
12044 prototype_map->set_prototype_info(*proto_info); 12067 prototype_map->set_prototype_info(*proto_info);
12045 return proto_info; 12068 return proto_info;
12046 } 12069 }
12047 12070
12071 // static
12072 void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
12073 Isolate* isolate) {
12074 if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
12075 // "False" is the implicit default value, so there's nothing to do.
12076 return;
12077 }
12078 GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
12079 }
12048 12080
12049 // static 12081 // static
12050 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, 12082 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
12051 Isolate* isolate) { 12083 Isolate* isolate) {
12052 Handle<Object> maybe_prototype(map->prototype(), isolate); 12084 Handle<Object> maybe_prototype(map->prototype(), isolate);
12053 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); 12085 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
12054 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); 12086 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
12055 // Ensure the prototype is registered with its own prototypes so its cell 12087 // Ensure the prototype is registered with its own prototypes so its cell
12056 // will be invalidated when necessary. 12088 // will be invalidated when necessary.
12057 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate), 12089 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
13034 shared()->expected_nof_properties(), 13066 shared()->expected_nof_properties(),
13035 instance_size, in_object_properties); 13067 instance_size, in_object_properties);
13036 } 13068 }
13037 13069
13038 13070
13039 void JSFunction::CalculateInstanceSizeForDerivedClass( 13071 void JSFunction::CalculateInstanceSizeForDerivedClass(
13040 InstanceType instance_type, int requested_internal_fields, 13072 InstanceType instance_type, int requested_internal_fields,
13041 int* instance_size, int* in_object_properties) { 13073 int* instance_size, int* in_object_properties) {
13042 Isolate* isolate = GetIsolate(); 13074 Isolate* isolate = GetIsolate();
13043 int expected_nof_properties = 0; 13075 int expected_nof_properties = 0;
13044 for (PrototypeIterator iter(isolate, this, 13076 for (PrototypeIterator iter(isolate, this, kStartAtReceiver); !iter.IsAtEnd();
13045 PrototypeIterator::START_AT_RECEIVER); 13077 iter.Advance()) {
13046 !iter.IsAtEnd(); iter.Advance()) {
13047 JSReceiver* current = iter.GetCurrent<JSReceiver>(); 13078 JSReceiver* current = iter.GetCurrent<JSReceiver>();
13048 if (!current->IsJSFunction()) break; 13079 if (!current->IsJSFunction()) break;
13049 JSFunction* func = JSFunction::cast(current); 13080 JSFunction* func = JSFunction::cast(current);
13050 SharedFunctionInfo* shared = func->shared(); 13081 SharedFunctionInfo* shared = func->shared();
13051 expected_nof_properties += shared->expected_nof_properties(); 13082 expected_nof_properties += shared->expected_nof_properties();
13052 if (!IsSubclassConstructor(shared->kind())) { 13083 if (!IsSubclassConstructor(shared->kind())) {
13053 break; 13084 break;
13054 } 13085 }
13055 } 13086 }
13056 CalculateInstanceSizeHelper(instance_type, requested_internal_fields, 13087 CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after
14860 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true); 14891 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true);
14861 14892
14862 bool dictionary_elements_in_chain = 14893 bool dictionary_elements_in_chain =
14863 object->map()->DictionaryElementsInPrototypeChainOnly(); 14894 object->map()->DictionaryElementsInPrototypeChainOnly();
14864 14895
14865 bool all_extensible = object->map()->is_extensible(); 14896 bool all_extensible = object->map()->is_extensible();
14866 Handle<JSObject> real_receiver = object; 14897 Handle<JSObject> real_receiver = object;
14867 if (from_javascript) { 14898 if (from_javascript) {
14868 // Find the first object in the chain whose prototype object is not 14899 // Find the first object in the chain whose prototype object is not
14869 // hidden. 14900 // hidden.
14870 PrototypeIterator iter(isolate, real_receiver, 14901 PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
14871 PrototypeIterator::START_AT_PROTOTYPE,
14872 PrototypeIterator::END_AT_NON_HIDDEN); 14902 PrototypeIterator::END_AT_NON_HIDDEN);
14873 while (!iter.IsAtEnd()) { 14903 while (!iter.IsAtEnd()) {
14874 // Casting to JSObject is fine because hidden prototypes are never 14904 // Casting to JSObject is fine because hidden prototypes are never
14875 // JSProxies. 14905 // JSProxies.
14876 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter); 14906 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
14877 iter.Advance(); 14907 iter.Advance();
14878 all_extensible = all_extensible && real_receiver->map()->is_extensible(); 14908 all_extensible = all_extensible && real_receiver->map()->is_extensible();
14879 } 14909 }
14880 } 14910 }
14881 Handle<Map> map(real_receiver->map()); 14911 Handle<Map> map(real_receiver->map());
(...skipping 12 matching lines...) Expand all
14894 if (!all_extensible) { 14924 if (!all_extensible) {
14895 RETURN_FAILURE(isolate, should_throw, 14925 RETURN_FAILURE(isolate, should_throw,
14896 NewTypeError(MessageTemplate::kNonExtensibleProto, object)); 14926 NewTypeError(MessageTemplate::kNonExtensibleProto, object));
14897 } 14927 }
14898 14928
14899 // Before we can set the prototype we need to be sure prototype cycles are 14929 // Before we can set the prototype we need to be sure prototype cycles are
14900 // prevented. It is sufficient to validate that the receiver is not in the 14930 // prevented. It is sufficient to validate that the receiver is not in the
14901 // new prototype chain. 14931 // new prototype chain.
14902 if (value->IsJSReceiver()) { 14932 if (value->IsJSReceiver()) {
14903 for (PrototypeIterator iter(isolate, JSReceiver::cast(*value), 14933 for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
14904 PrototypeIterator::START_AT_RECEIVER); 14934 kStartAtReceiver);
14905 !iter.IsAtEnd(); iter.Advance()) { 14935 !iter.IsAtEnd(); iter.Advance()) {
14906 if (iter.GetCurrent<JSReceiver>() == *object) { 14936 if (iter.GetCurrent<JSReceiver>() == *object) {
14907 // Cycle detected. 14937 // Cycle detected.
14908 RETURN_FAILURE(isolate, should_throw, 14938 RETURN_FAILURE(isolate, should_throw,
14909 NewTypeError(MessageTemplate::kCyclicProto)); 14939 NewTypeError(MessageTemplate::kCyclicProto));
14910 } 14940 }
14911 } 14941 }
14912 } 14942 }
14913 14943
14914 // Set the new prototype of the object. 14944 // Set the new prototype of the object.
(...skipping 3916 matching lines...) Expand 10 before | Expand all | Expand 10 after
18831 if (cell->value() != *new_value) { 18861 if (cell->value() != *new_value) {
18832 cell->set_value(*new_value); 18862 cell->set_value(*new_value);
18833 Isolate* isolate = cell->GetIsolate(); 18863 Isolate* isolate = cell->GetIsolate();
18834 cell->dependent_code()->DeoptimizeDependentCodeGroup( 18864 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18835 isolate, DependentCode::kPropertyCellChangedGroup); 18865 isolate, DependentCode::kPropertyCellChangedGroup);
18836 } 18866 }
18837 } 18867 }
18838 18868
18839 } // namespace internal 18869 } // namespace internal
18840 } // namespace v8 18870 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698