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

Side by Side Diff: src/objects.cc

Issue 468493002: Rewriting SetOwnPropertyIgnoreAttributes using the LookupIterator (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/runtime.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 "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/allocation-site-scopes.h" 8 #include "src/allocation-site-scopes.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 568
569 Handle<Object> argv[] = { value }; 569 Handle<Object> argv[] = { value };
570 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, 570 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver,
571 ARRAY_SIZE(argv), argv, true), 571 ARRAY_SIZE(argv), argv, true),
572 Object); 572 Object);
573 return value; 573 return value;
574 } 574 }
575 575
576 576
577 static bool FindAllCanReadHolder(LookupIterator* it) { 577 static bool FindAllCanReadHolder(LookupIterator* it) {
578 it->skip_interceptor();
579 it->skip_access_check();
580 for (; it->IsFound(); it->Next()) { 578 for (; it->IsFound(); it->Next()) {
581 if (it->state() == LookupIterator::PROPERTY && 579 if (it->state() == LookupIterator::PROPERTY &&
582 it->HasProperty() && 580 it->HasProperty() &&
583 it->property_kind() == LookupIterator::ACCESSOR) { 581 it->property_kind() == LookupIterator::ACCESSOR) {
584 Handle<Object> accessors = it->GetAccessors(); 582 Handle<Object> accessors = it->GetAccessors();
585 if (accessors->IsAccessorInfo()) { 583 if (accessors->IsAccessorInfo()) {
586 if (AccessorInfo::cast(*accessors)->all_can_read()) return true; 584 if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
587 } 585 }
588 } 586 }
589 } 587 }
(...skipping 21 matching lines...) Expand all
611 if (FindAllCanReadHolder(it)) 609 if (FindAllCanReadHolder(it))
612 return maybe(it->property_details().attributes()); 610 return maybe(it->property_details().attributes());
613 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); 611 it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
614 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), 612 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
615 Maybe<PropertyAttributes>()); 613 Maybe<PropertyAttributes>());
616 return maybe(ABSENT); 614 return maybe(ABSENT);
617 } 615 }
618 616
619 617
620 static bool FindAllCanWriteHolder(LookupIterator* it) { 618 static bool FindAllCanWriteHolder(LookupIterator* it) {
621 it->skip_interceptor();
622 it->skip_access_check();
623 for (; it->IsFound(); it->Next()) { 619 for (; it->IsFound(); it->Next()) {
624 if (it->state() == LookupIterator::PROPERTY && it->HasProperty() && 620 if (it->state() == LookupIterator::PROPERTY && it->HasProperty() &&
625 it->property_kind() == LookupIterator::ACCESSOR) { 621 it->property_kind() == LookupIterator::ACCESSOR) {
626 Handle<Object> accessors = it->GetAccessors(); 622 Handle<Object> accessors = it->GetAccessors();
627 if (accessors->IsAccessorInfo()) { 623 if (accessors->IsAccessorInfo()) {
628 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; 624 if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
629 } 625 }
630 } 626 }
631 } 627 }
632 return false; 628 return false;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 if (object->IsGlobalObject()) { 664 if (object->IsGlobalObject()) {
669 value = handle(Handle<PropertyCell>::cast(value)->value(), isolate); 665 value = handle(Handle<PropertyCell>::cast(value)->value(), isolate);
670 DCHECK(!value->IsTheHole()); 666 DCHECK(!value->IsTheHole());
671 } 667 }
672 DCHECK(!value->IsPropertyCell() && !value->IsCell()); 668 DCHECK(!value->IsPropertyCell() && !value->IsCell());
673 return value; 669 return value;
674 } 670 }
675 671
676 672
677 void JSObject::SetNormalizedProperty(Handle<JSObject> object, 673 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
678 const LookupResult* result,
679 Handle<Object> value) {
680 DCHECK(!object->HasFastProperties());
681 NameDictionary* property_dictionary = object->property_dictionary();
682 if (object->IsGlobalObject()) {
683 Handle<PropertyCell> cell(PropertyCell::cast(
684 property_dictionary->ValueAt(result->GetDictionaryEntry())));
685 PropertyCell::SetValueInferType(cell, value);
686 } else {
687 property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value);
688 }
689 }
690
691
692 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
693 Handle<Name> name, 674 Handle<Name> name,
694 Handle<Object> value, 675 Handle<Object> value,
695 PropertyDetails details) { 676 PropertyDetails details) {
696 DCHECK(!object->HasFastProperties()); 677 DCHECK(!object->HasFastProperties());
697 Handle<NameDictionary> property_dictionary(object->property_dictionary()); 678 Handle<NameDictionary> property_dictionary(object->property_dictionary());
698 679
699 if (!name->IsUniqueName()) { 680 if (!name->IsUniqueName()) {
700 name = object->GetIsolate()->factory()->InternalizeString( 681 name = object->GetIsolate()->factory()->InternalizeString(
701 Handle<String>::cast(name)); 682 Handle<String>::cast(name));
702 } 683 }
(...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1816 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { 1797 if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
1817 return MaybeHandle<Map>(); 1798 return MaybeHandle<Map>();
1818 } 1799 }
1819 1800
1820 // Allocate new instance descriptors with (name, constant) added. 1801 // Allocate new instance descriptors with (name, constant) added.
1821 ConstantDescriptor new_constant_desc(name, constant, attributes); 1802 ConstantDescriptor new_constant_desc(name, constant, attributes);
1822 return Map::CopyAddDescriptor(map, &new_constant_desc, flag); 1803 return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
1823 } 1804 }
1824 1805
1825 1806
1826 void JSObject::AddFastProperty(Handle<JSObject> object,
1827 Handle<Name> name,
1828 Handle<Object> value,
1829 PropertyAttributes attributes,
1830 StoreFromKeyed store_mode,
1831 TransitionFlag flag) {
1832 DCHECK(!object->IsJSGlobalProxy());
1833
1834 MaybeHandle<Map> maybe_map;
1835 if (value->IsJSFunction()) {
1836 maybe_map = Map::CopyWithConstant(
1837 handle(object->map()), name, value, attributes, flag);
1838 } else if (!object->map()->TooManyFastProperties(store_mode)) {
1839 Isolate* isolate = object->GetIsolate();
1840 Representation representation = value->OptimalRepresentation();
1841 maybe_map = Map::CopyWithField(
1842 handle(object->map(), isolate), name,
1843 value->OptimalType(isolate, representation),
1844 attributes, representation, flag);
1845 }
1846
1847 Handle<Map> new_map;
1848 if (!maybe_map.ToHandle(&new_map)) {
1849 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
1850 return;
1851 }
1852
1853 JSObject::MigrateToNewProperty(object, new_map, value);
1854 }
1855
1856
1857 void JSObject::AddSlowProperty(Handle<JSObject> object, 1807 void JSObject::AddSlowProperty(Handle<JSObject> object,
1858 Handle<Name> name, 1808 Handle<Name> name,
1859 Handle<Object> value, 1809 Handle<Object> value,
1860 PropertyAttributes attributes) { 1810 PropertyAttributes attributes) {
1861 DCHECK(!object->HasFastProperties()); 1811 DCHECK(!object->HasFastProperties());
1862 Isolate* isolate = object->GetIsolate(); 1812 Isolate* isolate = object->GetIsolate();
1863 Handle<NameDictionary> dict(object->property_dictionary()); 1813 Handle<NameDictionary> dict(object->property_dictionary());
1864 if (object->IsGlobalObject()) { 1814 if (object->IsGlobalObject()) {
1865 // In case name is an orphaned property reuse the cell. 1815 // In case name is an orphaned property reuse the cell.
1866 int entry = dict->FindEntry(name); 1816 int entry = dict->FindEntry(name);
(...skipping 12 matching lines...) Expand all
1879 PropertyCell::SetValueInferType(cell, value); 1829 PropertyCell::SetValueInferType(cell, value);
1880 value = cell; 1830 value = cell;
1881 } 1831 }
1882 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); 1832 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
1883 Handle<NameDictionary> result = 1833 Handle<NameDictionary> result =
1884 NameDictionary::Add(dict, name, value, details); 1834 NameDictionary::Add(dict, name, value, details);
1885 if (*dict != *result) object->set_properties(*result); 1835 if (*dict != *result) object->set_properties(*result);
1886 } 1836 }
1887 1837
1888 1838
1889 MaybeHandle<Object> JSObject::AddPropertyInternal(
1890 Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
1891 PropertyAttributes attributes, JSReceiver::StoreFromKeyed store_mode,
1892 ExtensibilityCheck extensibility_check, TransitionFlag transition_flag) {
1893 DCHECK(!object->IsJSGlobalProxy());
1894 Isolate* isolate = object->GetIsolate();
1895
1896 if (!name->IsUniqueName()) {
1897 name = isolate->factory()->InternalizeString(
1898 Handle<String>::cast(name));
1899 }
1900
1901 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
1902 !object->map()->is_extensible()) {
1903 Handle<Object> args[1] = {name};
1904 Handle<Object> error = isolate->factory()->NewTypeError(
1905 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
1906 return isolate->Throw<Object>(error);
1907 }
1908
1909 if (object->HasFastProperties()) {
1910 AddFastProperty(object, name, value, attributes, store_mode,
1911 transition_flag);
1912 }
1913
1914 if (!object->HasFastProperties()) {
1915 AddSlowProperty(object, name, value, attributes);
1916 }
1917
1918 if (object->map()->is_observed() &&
1919 *name != isolate->heap()->hidden_string()) {
1920 Handle<Object> old_value = isolate->factory()->the_hole_value();
1921 EnqueueChangeRecord(object, "add", name, old_value);
1922 }
1923
1924 return value;
1925 }
1926
1927
1928 Context* JSObject::GetCreationContext() { 1839 Context* JSObject::GetCreationContext() {
1929 Object* constructor = this->map()->constructor(); 1840 Object* constructor = this->map()->constructor();
1930 JSFunction* function; 1841 JSFunction* function;
1931 if (!constructor->IsJSFunction()) { 1842 if (!constructor->IsJSFunction()) {
1932 // Functions have null as a constructor, 1843 // Functions have null as a constructor,
1933 // but any JSFunction knows its context immediately. 1844 // but any JSFunction knows its context immediately.
1934 function = JSFunction::cast(this); 1845 function = JSFunction::cast(this);
1935 } else { 1846 } else {
1936 function = JSFunction::cast(constructor); 1847 function = JSFunction::cast(constructor);
1937 } 1848 }
(...skipping 14 matching lines...) Expand all
1952 Handle<Object> args[] = { type, object, name, old_value }; 1863 Handle<Object> args[] = { type, object, name, old_value };
1953 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4; 1864 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
1954 1865
1955 Execution::Call(isolate, 1866 Execution::Call(isolate,
1956 Handle<JSFunction>(isolate->observers_notify_change()), 1867 Handle<JSFunction>(isolate->observers_notify_change()),
1957 isolate->factory()->undefined_value(), 1868 isolate->factory()->undefined_value(),
1958 argc, args).Assert(); 1869 argc, args).Assert();
1959 } 1870 }
1960 1871
1961 1872
1962 static void ReplaceSlowProperty(Handle<JSObject> object,
1963 Handle<Name> name,
1964 Handle<Object> value,
1965 PropertyAttributes attributes) {
1966 NameDictionary* dictionary = object->property_dictionary();
1967 int old_index = dictionary->FindEntry(name);
1968 int new_enumeration_index = 0; // 0 means "Use the next available index."
1969 if (old_index != -1) {
1970 // All calls to ReplaceSlowProperty have had all transitions removed.
1971 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
1972 }
1973
1974 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
1975 JSObject::SetNormalizedProperty(object, name, value, new_details);
1976 }
1977
1978
1979 const char* Representation::Mnemonic() const { 1873 const char* Representation::Mnemonic() const {
1980 switch (kind_) { 1874 switch (kind_) {
1981 case kNone: return "v"; 1875 case kNone: return "v";
1982 case kTagged: return "t"; 1876 case kTagged: return "t";
1983 case kSmi: return "s"; 1877 case kSmi: return "s";
1984 case kDouble: return "d"; 1878 case kDouble: return "d";
1985 case kInteger32: return "i"; 1879 case kInteger32: return "i";
1986 case kHeapObject: return "h"; 1880 case kHeapObject: return "h";
1987 case kExternal: return "x"; 1881 case kExternal: return "x";
1988 default: 1882 default:
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after
3022 return SetDataProperty(it, value); 2916 return SetDataProperty(it, value);
3023 } 2917 }
3024 } 2918 }
3025 done = true; 2919 done = true;
3026 break; 2920 break;
3027 } 2921 }
3028 2922
3029 if (done) break; 2923 if (done) break;
3030 } 2924 }
3031 2925
3032 return AddDataProperty(it, value, NONE, strict_mode, store_mode); 2926 return AddDataProperty(it, value, NONE, strict_mode, store_mode,
2927 PERFORM_EXTENSIBILITY_CHECK);
3033 } 2928 }
3034 2929
3035 2930
3036 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it, 2931 MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
3037 Handle<Object> value, 2932 Handle<Object> value,
3038 StrictMode strict_mode) { 2933 StrictMode strict_mode) {
3039 if (strict_mode != STRICT) return value; 2934 if (strict_mode != STRICT) return value;
3040 2935
3041 Handle<Object> args[] = {it->name(), it->GetReceiver()}; 2936 Handle<Object> args[] = {it->name(), it->GetReceiver()};
3042 Handle<Object> error = it->factory()->NewTypeError( 2937 Handle<Object> error = it->factory()->NewTypeError(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3077 } 2972 }
3078 2973
3079 return value; 2974 return value;
3080 } 2975 }
3081 2976
3082 2977
3083 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, 2978 MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
3084 Handle<Object> value, 2979 Handle<Object> value,
3085 PropertyAttributes attributes, 2980 PropertyAttributes attributes,
3086 StrictMode strict_mode, 2981 StrictMode strict_mode,
3087 StoreFromKeyed store_mode) { 2982 StoreFromKeyed store_mode,
2983 ExtensibilityCheck check) {
3088 DCHECK(!it->GetReceiver()->IsJSProxy()); 2984 DCHECK(!it->GetReceiver()->IsJSProxy());
3089 if (!it->GetReceiver()->IsJSObject()) { 2985 if (!it->GetReceiver()->IsJSObject()) {
3090 // TODO(verwaest): Throw a TypeError with a more specific message. 2986 // TODO(verwaest): Throw a TypeError with a more specific message.
3091 return WriteToReadOnlyProperty(it, value, strict_mode); 2987 return WriteToReadOnlyProperty(it, value, strict_mode);
3092 } 2988 }
3093 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 2989 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
3094 2990
3095 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) 2991 // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
3096 // instead. If the prototype is Null, the proxy is detached. 2992 // instead. If the prototype is Null, the proxy is detached.
3097 if (receiver->IsJSGlobalProxy()) { 2993 if (receiver->IsJSGlobalProxy()) {
3098 // Trying to assign to a detached proxy. 2994 // Trying to assign to a detached proxy.
3099 PrototypeIterator iter(it->isolate(), receiver); 2995 PrototypeIterator iter(it->isolate(), receiver);
3100 if (iter.IsAtEnd()) return value; 2996 if (iter.IsAtEnd()) return value;
3101 receiver = 2997 receiver =
3102 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); 2998 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
3103 } 2999 }
3104 3000
3105 if (!receiver->map()->is_extensible()) { 3001 if (check == PERFORM_EXTENSIBILITY_CHECK &&
3002 !receiver->map()->is_extensible()) {
3106 if (strict_mode == SLOPPY) return value; 3003 if (strict_mode == SLOPPY) return value;
3107 3004
3108 Handle<Object> args[1] = {it->name()}; 3005 Handle<Object> args[1] = {it->name()};
3109 Handle<Object> error = it->factory()->NewTypeError( 3006 Handle<Object> error = it->factory()->NewTypeError(
3110 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); 3007 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
3111 return it->isolate()->Throw<Object>(error); 3008 return it->isolate()->Throw<Object>(error);
3112 } 3009 }
3113 3010
3114 // Possibly migrate to the most up-to-date map that will be able to store 3011 // Possibly migrate to the most up-to-date map that will be able to store
3115 // |value| under it->name() with |attributes|. 3012 // |value| under it->name() with |attributes|.
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after
3936 return false; 3833 return false;
3937 } 3834 }
3938 JSObject::MigrateToMap(object, new_map); 3835 JSObject::MigrateToMap(object, new_map);
3939 if (FLAG_trace_migration) { 3836 if (FLAG_trace_migration) {
3940 object->PrintInstanceMigration(stdout, *original_map, object->map()); 3837 object->PrintInstanceMigration(stdout, *original_map, object->map());
3941 } 3838 }
3942 return true; 3839 return true;
3943 } 3840 }
3944 3841
3945 3842
3946 MaybeHandle<Object> JSObject::SetPropertyUsingTransition(
3947 Handle<JSObject> object,
3948 LookupResult* lookup,
3949 Handle<Name> name,
3950 Handle<Object> value,
3951 PropertyAttributes attributes) {
3952 Handle<Map> transition_map(lookup->GetTransitionTarget());
3953 int descriptor = transition_map->LastAdded();
3954
3955 Handle<DescriptorArray> descriptors(transition_map->instance_descriptors());
3956 PropertyDetails details = descriptors->GetDetails(descriptor);
3957
3958 if (details.type() == CALLBACKS || attributes != details.attributes()) {
3959 // AddPropertyInternal will either normalize the object, or create a new
3960 // fast copy of the map. If we get a fast copy of the map, all field
3961 // representations will be tagged since the transition is omitted.
3962 return JSObject::AddPropertyInternal(
3963 object, name, value, attributes,
3964 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
3965 JSReceiver::OMIT_EXTENSIBILITY_CHECK, OMIT_TRANSITION);
3966 }
3967
3968 // Keep the target CONSTANT if the same value is stored.
3969 // TODO(verwaest): Also support keeping the placeholder
3970 // (value->IsUninitialized) as constant.
3971 if (!lookup->CanHoldValue(value)) {
3972 Representation field_representation = value->OptimalRepresentation();
3973 Handle<HeapType> field_type = value->OptimalType(
3974 lookup->isolate(), field_representation);
3975 transition_map = Map::GeneralizeRepresentation(
3976 transition_map, descriptor,
3977 field_representation, field_type, FORCE_FIELD);
3978 }
3979
3980 JSObject::MigrateToNewProperty(object, transition_map, value);
3981 return value;
3982 }
3983
3984
3985 void JSObject::MigrateToNewProperty(Handle<JSObject> object, 3843 void JSObject::MigrateToNewProperty(Handle<JSObject> object,
3986 Handle<Map> map, 3844 Handle<Map> map,
3987 Handle<Object> value) { 3845 Handle<Object> value) {
3988 JSObject::MigrateToMap(object, map); 3846 JSObject::MigrateToMap(object, map);
3989 if (map->GetLastDescriptorDetails().type() != FIELD) return; 3847 if (map->GetLastDescriptorDetails().type() != FIELD) return;
3990 object->WriteToField(map->LastAdded(), *value); 3848 object->WriteToField(map->LastAdded(), *value);
3991 } 3849 }
3992 3850
3993 3851
3994 void JSObject::WriteToField(int descriptor, Object* value) { 3852 void JSObject::WriteToField(int descriptor, Object* value) {
(...skipping 10 matching lines...) Expand all
4005 if (value->IsUninitialized()) return; 3863 if (value->IsUninitialized()) return;
4006 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); 3864 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
4007 DCHECK(box->IsMutableHeapNumber()); 3865 DCHECK(box->IsMutableHeapNumber());
4008 box->set_value(value->Number()); 3866 box->set_value(value->Number());
4009 } else { 3867 } else {
4010 FastPropertyAtPut(index, value); 3868 FastPropertyAtPut(index, value);
4011 } 3869 }
4012 } 3870 }
4013 3871
4014 3872
4015 void JSObject::SetPropertyToField(LookupResult* lookup, Handle<Object> value) {
4016 if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) {
4017 Representation field_representation = value->OptimalRepresentation();
4018 Handle<HeapType> field_type = value->OptimalType(
4019 lookup->isolate(), field_representation);
4020 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
4021 lookup->GetDescriptorIndex(),
4022 field_representation, field_type);
4023 }
4024 lookup->holder()->WriteToField(lookup->GetDescriptorIndex(), *value);
4025 }
4026
4027
4028 void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup,
4029 Handle<Name> name,
4030 Handle<Object> value,
4031 PropertyAttributes attributes) {
4032 Handle<JSObject> object(lookup->holder());
4033 if (object->map()->TooManyFastProperties(Object::MAY_BE_STORE_FROM_KEYED)) {
4034 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
4035 } else if (object->map()->is_prototype_map()) {
4036 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0);
4037 }
4038
4039 if (!object->HasFastProperties()) {
4040 ReplaceSlowProperty(object, name, value, attributes);
4041 ReoptimizeIfPrototype(object);
4042 return;
4043 }
4044
4045 int descriptor_index = lookup->GetDescriptorIndex();
4046 if (lookup->GetAttributes() == attributes) {
4047 JSObject::GeneralizeFieldRepresentation(object, descriptor_index,
4048 Representation::Tagged(),
4049 HeapType::Any(lookup->isolate()));
4050 } else {
4051 Handle<Map> old_map(object->map());
4052 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
4053 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch");
4054 JSObject::MigrateToMap(object, new_map);
4055 }
4056
4057 object->WriteToField(descriptor_index, *value);
4058 }
4059
4060
4061 void JSObject::SetPropertyToFieldWithAttributes(LookupResult* lookup,
4062 Handle<Name> name,
4063 Handle<Object> value,
4064 PropertyAttributes attributes) {
4065 if (lookup->GetAttributes() == attributes) {
4066 if (value->IsUninitialized()) return;
4067 SetPropertyToField(lookup, value);
4068 } else {
4069 ConvertAndSetOwnProperty(lookup, name, value, attributes);
4070 }
4071 }
4072
4073
4074 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name, 3873 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
4075 Handle<Object> value, 3874 Handle<Object> value,
4076 PropertyAttributes attributes) { 3875 PropertyAttributes attributes) {
4077 #ifdef DEBUG 3876 #ifdef DEBUG
4078 uint32_t index; 3877 uint32_t index;
4079 DCHECK(!object->IsJSProxy()); 3878 DCHECK(!object->IsJSProxy());
4080 DCHECK(!name->AsArrayIndex(&index)); 3879 DCHECK(!name->AsArrayIndex(&index));
4081 LookupIterator it(object, name, LookupIterator::CHECK_OWN_REAL); 3880 LookupIterator it(object, name, LookupIterator::CHECK_OWN_REAL);
4082 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); 3881 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
4083 DCHECK(maybe.has_value); 3882 DCHECK(maybe.has_value);
4084 DCHECK(!it.IsFound()); 3883 DCHECK(!it.IsFound());
4085 DCHECK(object->map()->is_extensible()); 3884 DCHECK(object->map()->is_extensible());
4086 #endif 3885 #endif
4087 SetOwnPropertyIgnoreAttributes(object, name, value, attributes, 3886 SetOwnPropertyIgnoreAttributes(object, name, value, attributes,
4088 OMIT_EXTENSIBILITY_CHECK).Check(); 3887 OMIT_EXTENSIBILITY_CHECK).Check();
4089 } 3888 }
4090 3889
4091 3890
4092 // Reconfigures a property to a data property with attributes, even if it is not 3891 // Reconfigures a property to a data property with attributes, even if it is not
4093 // reconfigurable. 3892 // reconfigurable.
4094 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( 3893 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
4095 Handle<JSObject> object, 3894 Handle<JSObject> object,
4096 Handle<Name> name, 3895 Handle<Name> name,
4097 Handle<Object> value, 3896 Handle<Object> value,
4098 PropertyAttributes attributes, 3897 PropertyAttributes attributes,
4099 ExtensibilityCheck extensibility_check, 3898 ExtensibilityCheck extensibility_check,
4100 StoreFromKeyed store_from_keyed, 3899 StoreFromKeyed store_from_keyed,
4101 ExecutableAccessorInfoHandling handling) { 3900 ExecutableAccessorInfoHandling handling) {
4102 DCHECK(!value->IsTheHole()); 3901 DCHECK(!value->IsTheHole());
4103 Isolate* isolate = object->GetIsolate(); 3902 LookupIterator it(object, name, LookupIterator::CHECK_HIDDEN_ACCESS);
3903 bool is_observed = object->map()->is_observed() &&
3904 *name != it.isolate()->heap()->hidden_string();
3905 for (; it.IsFound(); it.Next()) {
3906 switch (it.state()) {
3907 case LookupIterator::NOT_FOUND:
3908 case LookupIterator::JSPROXY:
3909 case LookupIterator::INTERCEPTOR:
3910 UNREACHABLE();
4104 3911
4105 // Make sure that the top context does not change when doing callbacks or 3912 case LookupIterator::ACCESS_CHECK:
4106 // interceptor calls. 3913 if (!it.isolate()->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4107 AssertNoContextChange ncc(isolate); 3914 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4108
4109 LookupResult lookup(isolate);
4110 object->LookupOwn(name, &lookup, true);
4111 if (!lookup.IsFound()) {
4112 object->map()->LookupTransition(*object, *name, &lookup);
4113 }
4114
4115 // Check access rights if needed.
4116 if (object->IsAccessCheckNeeded()) {
4117 if (!isolate->MayNamedAccess(object, name, v8::ACCESS_SET)) {
4118 LookupIterator it(object, name, LookupIterator::CHECK_OWN);
4119 return SetPropertyWithFailedAccessCheck(&it, value, SLOPPY);
4120 }
4121 }
4122
4123 if (object->IsJSGlobalProxy()) {
4124 PrototypeIterator iter(isolate, object);
4125 if (iter.IsAtEnd()) return value;
4126 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
4127 return SetOwnPropertyIgnoreAttributes(
4128 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name,
4129 value, attributes, extensibility_check);
4130 }
4131
4132 if (lookup.IsInterceptor() ||
4133 (lookup.IsDescriptorOrDictionary() && lookup.type() == CALLBACKS)) {
4134 object->LookupOwnRealNamedProperty(name, &lookup);
4135 }
4136
4137 // Check for accessor in prototype chain removed here in clone.
4138 if (!lookup.IsFound()) {
4139 object->map()->LookupTransition(*object, *name, &lookup);
4140 TransitionFlag flag = lookup.IsFound()
4141 ? OMIT_TRANSITION : INSERT_TRANSITION;
4142 // Neither properties nor transitions found.
4143 return AddPropertyInternal(object, name, value, attributes,
4144 store_from_keyed, extensibility_check, flag);
4145 }
4146
4147 Handle<Object> old_value = isolate->factory()->the_hole_value();
4148 PropertyAttributes old_attributes = ABSENT;
4149 bool is_observed = object->map()->is_observed() &&
4150 *name != isolate->heap()->hidden_string();
4151 if (is_observed && lookup.IsProperty()) {
4152 if (lookup.IsDataProperty()) {
4153 old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked();
4154 }
4155 old_attributes = lookup.GetAttributes();
4156 }
4157
4158 bool executed_set_prototype = false;
4159
4160 // Check of IsReadOnly removed from here in clone.
4161 if (lookup.IsTransition()) {
4162 Handle<Object> result;
4163 ASSIGN_RETURN_ON_EXCEPTION(
4164 isolate, result,
4165 SetPropertyUsingTransition(
4166 handle(lookup.holder()), &lookup, name, value, attributes),
4167 Object);
4168 } else {
4169 switch (lookup.type()) {
4170 case NORMAL:
4171 ReplaceSlowProperty(object, name, value, attributes);
4172 break;
4173 case FIELD:
4174 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4175 break;
4176 case CONSTANT:
4177 // Only replace the constant if necessary.
4178 if (lookup.GetAttributes() != attributes ||
4179 *value != lookup.GetConstant()) {
4180 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes);
4181 } 3915 }
4182 break; 3916 break;
4183 case CALLBACKS:
4184 {
4185 Handle<Object> callback(lookup.GetCallbackObject(), isolate);
4186 if (callback->IsExecutableAccessorInfo() &&
4187 handling == DONT_FORCE_FIELD) {
4188 Handle<Object> result;
4189 ASSIGN_RETURN_ON_EXCEPTION(
4190 isolate, result, JSObject::SetPropertyWithAccessor(
4191 object, name, value, handle(lookup.holder()),
4192 callback, STRICT),
4193 Object);
4194 3917
4195 if (attributes != lookup.GetAttributes()) { 3918 case LookupIterator::PROPERTY: {
4196 Handle<ExecutableAccessorInfo> new_data = 3919 if (!it.HasProperty()) break;
4197 Accessors::CloneAccessor( 3920 if (it.HolderIsNonGlobalHiddenPrototype()) break;
4198 isolate, Handle<ExecutableAccessorInfo>::cast(callback)); 3921 PropertyDetails details = it.property_details();
4199 new_data->set_property_attributes(attributes); 3922 Handle<Object> old_value = it.isolate()->factory()->the_hole_value();
4200 if (attributes & READ_ONLY) { 3923 switch (it.property_kind()) {
4201 // This way we don't have to introduce a lookup to the setter, 3924 case LookupIterator::ACCESSOR: {
4202 // simply make it unavailable to reflect the attributes. 3925 // Ensure the context isn't changed after calling into accessors.
4203 new_data->clear_setter(); 3926 AssertNoContextChange ncc(it.isolate());
3927
3928 Handle<Object> accessors = it.GetAccessors();
3929
3930 if (is_observed && accessors->IsAccessorInfo()) {
3931 ASSIGN_RETURN_ON_EXCEPTION(
3932 it.isolate(), old_value,
3933 GetPropertyWithAccessor(it.GetReceiver(), it.name(),
3934 it.GetHolder<JSObject>(), accessors),
3935 Object);
4204 } 3936 }
4205 3937
4206 SetPropertyCallback(object, name, new_data, attributes); 3938 // Special handling for ExecutableAccessorInfo, which behaves like a
3939 // data property.
3940 if (handling == DONT_FORCE_FIELD &&
3941 accessors->IsExecutableAccessorInfo()) {
3942 Handle<Object> result;
3943 ASSIGN_RETURN_ON_EXCEPTION(
3944 it.isolate(), result,
3945 JSObject::SetPropertyWithAccessor(
3946 it.GetReceiver(), it.name(), value,
3947 it.GetHolder<JSObject>(), accessors, STRICT),
3948 Object);
3949 DCHECK(result->SameValue(*value));
3950
3951 if (details.attributes() == attributes) {
3952 // Regular property update if the attributes match.
3953 if (is_observed && !old_value->SameValue(*value)) {
3954 // If we are setting the prototype of a function and are
3955 // observed, don't send change records because the prototype
3956 // handles that itself.
3957 if (!object->IsJSFunction() ||
3958 !Name::Equals(it.isolate()->factory()->prototype_string(),
3959 name) ||
3960 !Handle<JSFunction>::cast(object)
3961 ->should_have_prototype()) {
3962 EnqueueChangeRecord(object, "update", name, old_value);
3963 }
3964 }
3965 return value;
3966 }
3967
3968 // Reconfigure the accessor if attributes mismatch.
3969 Handle<ExecutableAccessorInfo> new_data =
3970 Accessors::CloneAccessor(
3971 it.isolate(),
3972 Handle<ExecutableAccessorInfo>::cast(accessors));
3973 new_data->set_property_attributes(attributes);
3974 // By clearing the setter we don't have to introduce a lookup to
3975 // the setter, simply make it unavailable to reflect the
3976 // attributes.
3977 if (attributes & READ_ONLY) new_data->clear_setter();
3978 SetPropertyCallback(object, name, new_data, attributes);
3979 if (is_observed) {
3980 if (old_value->SameValue(*value)) {
3981 old_value = it.isolate()->factory()->the_hole_value();
3982 }
3983 EnqueueChangeRecord(object, "reconfigure", name, old_value);
3984 }
3985 return value;
3986 }
3987
3988 // Regular accessor. Reconfigure to data property.
3989 break;
4207 } 3990 }
4208 if (is_observed) { 3991
4209 // If we are setting the prototype of a function and are observed, 3992 case LookupIterator::DATA:
4210 // don't send change records because the prototype handles that 3993 // Regular property update if the attributes match.
4211 // itself. 3994 if (details.attributes() == attributes) {
4212 executed_set_prototype = object->IsJSFunction() && 3995 return SetDataProperty(&it, value);
4213 String::Equals(isolate->factory()->prototype_string(), 3996 }
4214 Handle<String>::cast(name)) && 3997 // Reconfigure the data property if the attributes mismatch.
4215 Handle<JSFunction>::cast(object)->should_have_prototype(); 3998 if (is_observed) old_value = it.GetDataValue();
3999 }
4000
4001 it.ReconfigureDataProperty(value, attributes);
4002 it.PrepareForDataProperty(value);
4003 it.WriteDataValue(value);
4004
4005 if (is_observed) {
4006 if (old_value->SameValue(*value)) {
4007 old_value = it.isolate()->factory()->the_hole_value();
4216 } 4008 }
4217 } else { 4009 EnqueueChangeRecord(object, "reconfigure", name, old_value);
4218 ConvertAndSetOwnProperty(&lookup, name, value, attributes);
4219 } 4010 }
4220 break;
4221 }
4222 case NONEXISTENT:
4223 case HANDLER:
4224 case INTERCEPTOR:
4225 UNREACHABLE();
4226 }
4227 }
4228 4011
4229 if (is_observed && !executed_set_prototype) { 4012 return value;
4230 if (lookup.IsTransition()) {
4231 EnqueueChangeRecord(object, "add", name, old_value);
4232 } else if (old_value->IsTheHole()) {
4233 EnqueueChangeRecord(object, "reconfigure", name, old_value);
4234 } else {
4235 LookupResult new_lookup(isolate);
4236 object->LookupOwn(name, &new_lookup, true);
4237 bool value_changed = false;
4238 if (new_lookup.IsDataProperty()) {
4239 Handle<Object> new_value =
4240 Object::GetPropertyOrElement(object, name).ToHandleChecked();
4241 value_changed = !old_value->SameValue(*new_value);
4242 }
4243 if (new_lookup.GetAttributes() != old_attributes) {
4244 if (!value_changed) old_value = isolate->factory()->the_hole_value();
4245 EnqueueChangeRecord(object, "reconfigure", name, old_value);
4246 } else if (value_changed) {
4247 EnqueueChangeRecord(object, "update", name, old_value);
4248 } 4013 }
4249 } 4014 }
4250 } 4015 }
4251 4016
4252 return value; 4017 return AddDataProperty(&it, value, attributes, STRICT, store_from_keyed,
4018 extensibility_check);
4253 } 4019 }
4254 4020
4255 4021
4256 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( 4022 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
4257 Handle<JSObject> holder, 4023 Handle<JSObject> holder,
4258 Handle<Object> receiver, 4024 Handle<Object> receiver,
4259 Handle<Name> name) { 4025 Handle<Name> name) {
4260 // TODO(rossberg): Support symbols in the API. 4026 // TODO(rossberg): Support symbols in the API.
4261 if (name->IsSymbol()) return maybe(ABSENT); 4027 if (name->IsSymbol()) return maybe(ABSENT);
4262 4028
(...skipping 3124 matching lines...) Expand 10 before | Expand all | Expand 10 after
7387 7153
7388 Handle<Map> result; 7154 Handle<Map> result;
7389 if (!maybe_map.ToHandle(&result)) { 7155 if (!maybe_map.ToHandle(&result)) {
7390 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); 7156 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
7391 } 7157 }
7392 7158
7393 return result; 7159 return result;
7394 } 7160 }
7395 7161
7396 7162
7163 Handle<Map> Map::ReconfigureDataProperty(Handle<Map> map, int descriptor,
7164 PropertyAttributes attributes) {
7165 // Dictionaries have to be reconfigured in-place.
7166 DCHECK(!map->is_dictionary_map());
7167
7168 // For now, give up on transitioning and just create a unique map.
7169 // TODO(verwaest/ishell): Cache transitions with different attributes.
7170 return CopyGeneralizeAllRepresentations(map, descriptor, FORCE_FIELD,
7171 attributes, "attributes mismatch");
7172 }
7173
7174
7397 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, 7175 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
7398 Descriptor* descriptor, 7176 Descriptor* descriptor,
7399 TransitionFlag flag) { 7177 TransitionFlag flag) {
7400 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 7178 Handle<DescriptorArray> descriptors(map->instance_descriptors());
7401 7179
7402 // Ensure the key is unique. 7180 // Ensure the key is unique.
7403 descriptor->KeyToUniqueName(); 7181 descriptor->KeyToUniqueName();
7404 7182
7405 if (flag == INSERT_TRANSITION && 7183 if (flag == INSERT_TRANSITION &&
7406 map->owns_descriptors() && 7184 map->owns_descriptors() &&
(...skipping 9522 matching lines...) Expand 10 before | Expand all | Expand 10 after
16929 #define ERROR_MESSAGES_TEXTS(C, T) T, 16707 #define ERROR_MESSAGES_TEXTS(C, T) T,
16930 static const char* error_messages_[] = { 16708 static const char* error_messages_[] = {
16931 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16709 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16932 }; 16710 };
16933 #undef ERROR_MESSAGES_TEXTS 16711 #undef ERROR_MESSAGES_TEXTS
16934 return error_messages_[reason]; 16712 return error_messages_[reason];
16935 } 16713 }
16936 16714
16937 16715
16938 } } // namespace v8::internal 16716 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698