OLD | NEW |
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 5806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5817 Handle<JSProxy> proxy) { | 5817 Handle<JSProxy> proxy) { |
5818 return handle(proxy->hash(), isolate); | 5818 return handle(proxy->hash(), isolate); |
5819 } | 5819 } |
5820 | 5820 |
5821 | 5821 |
5822 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { | 5822 Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { |
5823 return GetOrCreateIdentityHashHelper(proxy); | 5823 return GetOrCreateIdentityHashHelper(proxy); |
5824 } | 5824 } |
5825 | 5825 |
5826 | 5826 |
5827 Object* JSObject::GetHiddenProperty(Handle<Name> key) { | |
5828 DisallowHeapAllocation no_gc; | |
5829 DCHECK(key->IsUniqueName()); | |
5830 if (IsJSGlobalProxy()) { | |
5831 // For a proxy, use the prototype as target object. | |
5832 PrototypeIterator iter(GetIsolate(), this); | |
5833 // If the proxy is detached, return undefined. | |
5834 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); | |
5835 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | |
5836 return iter.GetCurrent<JSObject>()->GetHiddenProperty(key); | |
5837 } | |
5838 DCHECK(!IsJSGlobalProxy()); | |
5839 Object* inline_value = GetHiddenPropertiesHashTable(); | |
5840 | |
5841 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | |
5842 | |
5843 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | |
5844 Object* entry = hashtable->Lookup(key); | |
5845 return entry; | |
5846 } | |
5847 | |
5848 | |
5849 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, | |
5850 Handle<Name> key, | |
5851 Handle<Object> value) { | |
5852 Isolate* isolate = object->GetIsolate(); | |
5853 | |
5854 DCHECK(key->IsUniqueName()); | |
5855 if (object->IsJSGlobalProxy()) { | |
5856 // For a proxy, use the prototype as target object. | |
5857 PrototypeIterator iter(isolate, object); | |
5858 // If the proxy is detached, return undefined. | |
5859 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | |
5860 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | |
5861 return SetHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter), key, | |
5862 value); | |
5863 } | |
5864 DCHECK(!object->IsJSGlobalProxy()); | |
5865 | |
5866 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | |
5867 | |
5868 Handle<ObjectHashTable> hashtable = | |
5869 GetOrCreateHiddenPropertiesHashtable(object); | |
5870 | |
5871 // If it was found, check if the key is already in the dictionary. | |
5872 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, | |
5873 value); | |
5874 if (*new_table != *hashtable) { | |
5875 // If adding the key expanded the dictionary (i.e., Add returned a new | |
5876 // dictionary), store it back to the object. | |
5877 SetHiddenPropertiesHashTable(object, new_table); | |
5878 } | |
5879 | |
5880 // Return this to mark success. | |
5881 return object; | |
5882 } | |
5883 | |
5884 | |
5885 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { | |
5886 Isolate* isolate = object->GetIsolate(); | |
5887 DCHECK(key->IsUniqueName()); | |
5888 | |
5889 if (object->IsJSGlobalProxy()) { | |
5890 PrototypeIterator iter(isolate, object); | |
5891 if (iter.IsAtEnd()) return; | |
5892 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | |
5893 return DeleteHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter), | |
5894 key); | |
5895 } | |
5896 | |
5897 Object* inline_value = object->GetHiddenPropertiesHashTable(); | |
5898 | |
5899 if (inline_value->IsUndefined()) return; | |
5900 | |
5901 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | |
5902 bool was_present = false; | |
5903 ObjectHashTable::Remove(hashtable, key, &was_present); | |
5904 } | |
5905 | |
5906 | |
5907 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { | |
5908 Isolate* isolate = object->GetIsolate(); | |
5909 Handle<Symbol> hidden = isolate->factory()->hidden_properties_symbol(); | |
5910 LookupIterator it(object, hidden, object); | |
5911 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); | |
5912 // Cannot get an exception since the hidden_properties_symbol isn't exposed to | |
5913 // JS. | |
5914 DCHECK(maybe.IsJust()); | |
5915 return maybe.FromJust() != ABSENT; | |
5916 } | |
5917 | |
5918 | |
5919 Object* JSObject::GetHiddenPropertiesHashTable() { | |
5920 DCHECK(!IsJSGlobalProxy()); | |
5921 if (HasFastProperties()) { | |
5922 // If the object has fast properties, check whether the first slot | |
5923 // in the descriptor array matches the hidden string. Since the | |
5924 // hidden strings hash code is zero (and no other name has hash | |
5925 // code zero) it will always occupy the first entry if present. | |
5926 DescriptorArray* descriptors = this->map()->instance_descriptors(); | |
5927 if (descriptors->number_of_descriptors() > 0) { | |
5928 int sorted_index = descriptors->GetSortedKeyIndex(0); | |
5929 if (descriptors->GetKey(sorted_index) == | |
5930 GetHeap()->hidden_properties_symbol() && | |
5931 sorted_index < map()->NumberOfOwnDescriptors()) { | |
5932 DCHECK(descriptors->GetType(sorted_index) == DATA); | |
5933 DCHECK(descriptors->GetDetails(sorted_index).representation(). | |
5934 IsCompatibleForLoad(Representation::Tagged())); | |
5935 FieldIndex index = FieldIndex::ForDescriptor(this->map(), | |
5936 sorted_index); | |
5937 return this->RawFastPropertyAt(index); | |
5938 } else { | |
5939 return GetHeap()->undefined_value(); | |
5940 } | |
5941 } else { | |
5942 return GetHeap()->undefined_value(); | |
5943 } | |
5944 } else { | |
5945 Isolate* isolate = GetIsolate(); | |
5946 Handle<Symbol> hidden = isolate->factory()->hidden_properties_symbol(); | |
5947 Handle<JSObject> receiver(this, isolate); | |
5948 LookupIterator it(receiver, hidden, receiver); | |
5949 // Access check is always skipped for the hidden string anyways. | |
5950 return *GetDataProperty(&it); | |
5951 } | |
5952 } | |
5953 | |
5954 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable( | |
5955 Handle<JSObject> object) { | |
5956 Isolate* isolate = object->GetIsolate(); | |
5957 | |
5958 static const int kInitialCapacity = 4; | |
5959 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | |
5960 if (inline_value->IsHashTable()) { | |
5961 return Handle<ObjectHashTable>::cast(inline_value); | |
5962 } | |
5963 | |
5964 Handle<ObjectHashTable> hashtable = ObjectHashTable::New( | |
5965 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); | |
5966 | |
5967 DCHECK(inline_value->IsUndefined()); | |
5968 SetHiddenPropertiesHashTable(object, hashtable); | |
5969 return hashtable; | |
5970 } | |
5971 | |
5972 | |
5973 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | |
5974 Handle<Object> value) { | |
5975 DCHECK(!object->IsJSGlobalProxy()); | |
5976 Isolate* isolate = object->GetIsolate(); | |
5977 Handle<Symbol> name = isolate->factory()->hidden_properties_symbol(); | |
5978 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert(); | |
5979 return object; | |
5980 } | |
5981 | |
5982 | |
5983 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it, | 5827 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it, |
5984 ShouldThrow should_throw) { | 5828 ShouldThrow should_throw) { |
5985 Isolate* isolate = it->isolate(); | 5829 Isolate* isolate = it->isolate(); |
5986 // Make sure that the top context does not change when doing callbacks or | 5830 // Make sure that the top context does not change when doing callbacks or |
5987 // interceptor calls. | 5831 // interceptor calls. |
5988 AssertNoContextChange ncc(isolate); | 5832 AssertNoContextChange ncc(isolate); |
5989 | 5833 |
5990 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 5834 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
5991 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); | 5835 Handle<InterceptorInfo> interceptor(it->GetInterceptor()); |
5992 if (interceptor->deleter()->IsUndefined()) return Nothing<bool>(); | 5836 if (interceptor->deleter()->IsUndefined()) return Nothing<bool>(); |
(...skipping 12839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18832 if (cell->value() != *new_value) { | 18676 if (cell->value() != *new_value) { |
18833 cell->set_value(*new_value); | 18677 cell->set_value(*new_value); |
18834 Isolate* isolate = cell->GetIsolate(); | 18678 Isolate* isolate = cell->GetIsolate(); |
18835 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18679 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18836 isolate, DependentCode::kPropertyCellChangedGroup); | 18680 isolate, DependentCode::kPropertyCellChangedGroup); |
18837 } | 18681 } |
18838 } | 18682 } |
18839 | 18683 |
18840 } // namespace internal | 18684 } // namespace internal |
18841 } // namespace v8 | 18685 } // namespace v8 |
OLD | NEW |