| 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 |