Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1021 return context->symbol_function()->instance_prototype(); | 1021 return context->symbol_function()->instance_prototype(); |
| 1022 } | 1022 } |
| 1023 if (heap_object->IsBoolean()) { | 1023 if (heap_object->IsBoolean()) { |
| 1024 return context->boolean_function()->instance_prototype(); | 1024 return context->boolean_function()->instance_prototype(); |
| 1025 } else { | 1025 } else { |
| 1026 return isolate->heap()->null_value(); | 1026 return isolate->heap()->null_value(); |
| 1027 } | 1027 } |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 | 1030 |
| 1031 MaybeObject* Object::GetHash(CreationFlag flag) { | 1031 Object* Object::GetHash() { |
| 1032 // The object is either a number, a name, an odd-ball, | 1032 // The object is either a number, a name, an odd-ball, |
| 1033 // a real JS object, or a Harmony proxy. | 1033 // a real JS object, or a Harmony proxy. |
| 1034 if (IsNumber()) { | 1034 if (IsNumber()) { |
| 1035 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); | 1035 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); |
| 1036 return Smi::FromInt(hash & Smi::kMaxValue); | 1036 return Smi::FromInt(hash & Smi::kMaxValue); |
| 1037 } | 1037 } |
| 1038 if (IsName()) { | 1038 if (IsName()) { |
| 1039 uint32_t hash = Name::cast(this)->Hash(); | 1039 uint32_t hash = Name::cast(this)->Hash(); |
| 1040 return Smi::FromInt(hash); | 1040 return Smi::FromInt(hash); |
| 1041 } | 1041 } |
| 1042 if (IsOddball()) { | 1042 if (IsOddball()) { |
| 1043 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); | 1043 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
| 1044 return Smi::FromInt(hash); | 1044 return Smi::FromInt(hash); |
| 1045 } | 1045 } |
| 1046 if (IsJSReceiver()) { | |
| 1047 return JSReceiver::cast(this)->GetIdentityHash(flag); | |
| 1048 } | |
| 1049 | 1046 |
| 1050 UNREACHABLE(); | 1047 ASSERT(IsJSReceiver()); |
|
rafaelw
2013/11/04 15:12:01
Note that I've changed this for consistency with G
| |
| 1051 return Smi::FromInt(0); | 1048 return JSReceiver::cast(this)->GetIdentityHash(); |
| 1052 } | 1049 } |
| 1053 | 1050 |
| 1054 | 1051 |
| 1052 Handle<Object> Object::GetOrCreateHash(Handle<Object> object, | |
| 1053 Isolate* isolate) { | |
| 1054 Handle<Object> hash(object->GetHash(), isolate); | |
| 1055 if (hash->IsSmi()) | |
| 1056 return hash; | |
| 1057 | |
| 1058 ASSERT(object->IsJSReceiver()); | |
| 1059 return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object)); | |
| 1060 } | |
| 1061 | |
| 1062 | |
| 1055 bool Object::SameValue(Object* other) { | 1063 bool Object::SameValue(Object* other) { |
| 1056 if (other == this) return true; | 1064 if (other == this) return true; |
| 1057 | 1065 |
| 1058 // The object is either a number, a name, an odd-ball, | 1066 // The object is either a number, a name, an odd-ball, |
| 1059 // a real JS object, or a Harmony proxy. | 1067 // a real JS object, or a Harmony proxy. |
| 1060 if (IsNumber() && other->IsNumber()) { | 1068 if (IsNumber() && other->IsNumber()) { |
| 1061 double this_value = Number(); | 1069 double this_value = Number(); |
| 1062 double other_value = other->Number(); | 1070 double other_value = other->Number(); |
| 1063 bool equal = this_value == other_value; | 1071 bool equal = this_value == other_value; |
| 1064 // SameValue(NaN, NaN) is true. | 1072 // SameValue(NaN, NaN) is true. |
| (...skipping 2683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3748 Handle<JSReceiver> receiver(receiver_raw); | 3756 Handle<JSReceiver> receiver(receiver_raw); |
| 3749 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3757 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 3750 return proxy->GetPropertyAttributeWithHandler(*receiver, *name); | 3758 return proxy->GetPropertyAttributeWithHandler(*receiver, *name); |
| 3751 } | 3759 } |
| 3752 | 3760 |
| 3753 | 3761 |
| 3754 void JSProxy::Fix(Handle<JSProxy> proxy) { | 3762 void JSProxy::Fix(Handle<JSProxy> proxy) { |
| 3755 Isolate* isolate = proxy->GetIsolate(); | 3763 Isolate* isolate = proxy->GetIsolate(); |
| 3756 | 3764 |
| 3757 // Save identity hash. | 3765 // Save identity hash. |
| 3758 Handle<Object> hash = JSProxy::GetIdentityHash(proxy, OMIT_CREATION); | 3766 Handle<Object> hash(proxy->GetIdentityHash(), isolate); |
| 3759 | 3767 |
| 3760 if (proxy->IsJSFunctionProxy()) { | 3768 if (proxy->IsJSFunctionProxy()) { |
| 3761 isolate->factory()->BecomeJSFunction(proxy); | 3769 isolate->factory()->BecomeJSFunction(proxy); |
| 3762 // Code will be set on the JavaScript side. | 3770 // Code will be set on the JavaScript side. |
| 3763 } else { | 3771 } else { |
| 3764 isolate->factory()->BecomeJSObject(proxy); | 3772 isolate->factory()->BecomeJSObject(proxy); |
| 3765 } | 3773 } |
| 3766 ASSERT(proxy->IsJSObject()); | 3774 ASSERT(proxy->IsJSObject()); |
| 3767 | 3775 |
| 3768 // Inherit identity, if it was present. | 3776 // Inherit identity, if it was present. |
| 3769 if (hash->IsSmi()) { | 3777 if (hash->IsSmi()) { |
| 3770 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), Smi::cast(*hash)); | 3778 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), |
| 3779 Handle<Smi>::cast(hash)); | |
| 3771 } | 3780 } |
| 3772 } | 3781 } |
| 3773 | 3782 |
| 3774 | 3783 |
| 3775 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, | 3784 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, |
| 3776 Handle<Object> derived, | 3785 Handle<Object> derived, |
| 3777 int argc, | 3786 int argc, |
| 3778 Handle<Object> argv[]) { | 3787 Handle<Object> argv[]) { |
| 3779 Isolate* isolate = GetIsolate(); | 3788 Isolate* isolate = GetIsolate(); |
| 3780 Handle<Object> handler(this->handler(), isolate); | 3789 Handle<Object> handler(this->handler(), isolate); |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4781 // within a smi. | 4790 // within a smi. |
| 4782 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; | 4791 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; |
| 4783 attempts++; | 4792 attempts++; |
| 4784 } while (hash_value == 0 && attempts < 30); | 4793 } while (hash_value == 0 && attempts < 30); |
| 4785 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 4794 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 4786 | 4795 |
| 4787 return Smi::FromInt(hash_value); | 4796 return Smi::FromInt(hash_value); |
| 4788 } | 4797 } |
| 4789 | 4798 |
| 4790 | 4799 |
| 4791 void JSObject::SetIdentityHash(Handle<JSObject> object, Smi* hash) { | 4800 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { |
| 4792 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 4801 Isolate* isolate = object->GetIsolate(); |
| 4793 object->SetHiddenProperty( | 4802 JSObject::SetHiddenProperty( |
|
Michael Starzinger
2013/11/04 17:58:58
nit: The explicit name-space prefix "JSObject::" s
rafaelw
2013/11/05 09:56:54
Done.
| |
| 4794 object->GetHeap()->identity_hash_string(), hash)); | 4803 object, isolate->factory()->identity_hash_string(), hash); |
| 4795 } | 4804 } |
| 4796 | 4805 |
| 4797 | 4806 |
| 4798 int JSObject::GetIdentityHash(Handle<JSObject> object) { | 4807 int JSObject::GetIdentityHash(Handle<JSObject> object) { |
| 4799 CALL_AND_RETRY_OR_DIE(object->GetIsolate(), | 4808 Handle<Object> hash = JSObject::GetOrCreateIdentityHash(object); |
|
rafaelw
2013/11/04 15:12:01
I *think* this is right. It's a bit hard for me to
Michael Starzinger
2013/11/04 17:58:58
AFAICT, the return value of JSObject::GetOrCreateI
rafaelw
2013/11/05 09:56:54
Done.
| |
| 4800 object->GetIdentityHash(ALLOW_CREATION), | 4809 return hash->IsSmi() ? Handle<Smi>::cast(hash)->value() : 0; |
| 4801 return Smi::cast(__object__)->value(), | |
| 4802 return 0); | |
| 4803 } | 4810 } |
| 4804 | 4811 |
| 4805 | 4812 |
| 4806 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { | 4813 Object* JSObject::GetIdentityHash() { |
| 4807 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string()); | 4814 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string()); |
| 4808 if (stored_value->IsSmi()) return stored_value; | 4815 return stored_value->IsSmi() ? stored_value : GetHeap()->undefined_value(); |
| 4816 } | |
| 4809 | 4817 |
| 4810 // Do not generate permanent identity hash code if not requested. | |
| 4811 if (flag == OMIT_CREATION) return GetHeap()->undefined_value(); | |
| 4812 | 4818 |
| 4813 Smi* hash = GenerateIdentityHash(); | 4819 Handle<Object> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { |
| 4814 MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_string(), | 4820 Handle<Object> hash(object->GetIdentityHash(), object->GetIsolate()); |
| 4815 hash); | 4821 if (hash->IsSmi()) |
| 4816 if (result->IsFailure()) return result; | 4822 return hash; |
| 4817 if (result->ToObjectUnchecked()->IsUndefined()) { | 4823 |
| 4824 Isolate* isolate = object->GetIsolate(); | |
| 4825 | |
| 4826 hash = handle(object->GenerateIdentityHash(), isolate); | |
| 4827 Handle<Object> result = JSObject::SetHiddenProperty(object, | |
| 4828 isolate->factory()->identity_hash_string(), hash); | |
| 4829 | |
| 4830 if (result->IsUndefined()) { | |
| 4818 // Trying to get hash of detached proxy. | 4831 // Trying to get hash of detached proxy. |
| 4819 return Smi::FromInt(0); | 4832 return handle(Smi::FromInt(0), isolate); |
| 4820 } | 4833 } |
| 4834 | |
| 4821 return hash; | 4835 return hash; |
| 4822 } | 4836 } |
| 4823 | 4837 |
| 4824 | 4838 |
| 4825 Handle<Object> JSProxy::GetIdentityHash(Handle<JSProxy> proxy, | 4839 Object* JSProxy::GetIdentityHash() { |
| 4826 CreationFlag flag) { | 4840 return this->hash(); |
| 4827 CALL_HEAP_FUNCTION(proxy->GetIsolate(), proxy->GetIdentityHash(flag), Object); | |
| 4828 } | 4841 } |
| 4829 | 4842 |
| 4830 | 4843 |
| 4831 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) { | 4844 Handle<Object> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { |
| 4832 Object* hash = this->hash(); | 4845 Isolate* isolate = proxy->GetIsolate(); |
| 4833 if (!hash->IsSmi() && flag == ALLOW_CREATION) { | 4846 |
| 4834 hash = GenerateIdentityHash(); | 4847 Handle<Object> hash(proxy->GetIdentityHash(), isolate); |
| 4835 set_hash(hash); | 4848 if (hash->IsSmi()) |
| 4836 } | 4849 return hash; |
| 4850 | |
| 4851 hash = handle(proxy->GenerateIdentityHash(), isolate); | |
| 4852 proxy->set_hash(*hash); | |
| 4837 return hash; | 4853 return hash; |
| 4838 } | 4854 } |
| 4839 | 4855 |
| 4840 | 4856 |
| 4841 Object* JSObject::GetHiddenProperty(Name* key) { | 4857 Object* JSObject::GetHiddenProperty(Name* key) { |
| 4842 ASSERT(key->IsUniqueName()); | 4858 ASSERT(key->IsUniqueName()); |
| 4843 if (IsJSGlobalProxy()) { | 4859 if (IsJSGlobalProxy()) { |
| 4844 // For a proxy, use the prototype as target object. | 4860 // For a proxy, use the prototype as target object. |
| 4845 Object* proxy_parent = GetPrototype(); | 4861 Object* proxy_parent = GetPrototype(); |
| 4846 // If the proxy is detached, return undefined. | 4862 // If the proxy is detached, return undefined. |
| 4847 if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); | 4863 if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); |
| 4848 ASSERT(proxy_parent->IsJSGlobalObject()); | 4864 ASSERT(proxy_parent->IsJSGlobalObject()); |
| 4849 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); | 4865 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); |
| 4850 } | 4866 } |
| 4851 ASSERT(!IsJSGlobalProxy()); | 4867 ASSERT(!IsJSGlobalProxy()); |
| 4852 MaybeObject* hidden_lookup = | 4868 Object* inline_value = GetHiddenPropertiesHashTable(); |
| 4853 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); | |
| 4854 Object* inline_value = hidden_lookup->ToObjectUnchecked(); | |
| 4855 | 4869 |
| 4856 if (inline_value->IsSmi()) { | 4870 if (inline_value->IsSmi()) { |
| 4857 // Handle inline-stored identity hash. | 4871 // Handle inline-stored identity hash. |
| 4858 if (key == GetHeap()->identity_hash_string()) { | 4872 if (key == GetHeap()->identity_hash_string()) { |
| 4859 return inline_value; | 4873 return inline_value; |
| 4860 } else { | 4874 } else { |
| 4861 return GetHeap()->the_hole_value(); | 4875 return GetHeap()->the_hole_value(); |
| 4862 } | 4876 } |
| 4863 } | 4877 } |
| 4864 | 4878 |
| 4865 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | 4879 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
| 4866 | 4880 |
| 4867 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | 4881 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
| 4868 Object* entry = hashtable->Lookup(key); | 4882 Object* entry = hashtable->Lookup(key); |
| 4869 return entry; | 4883 return entry; |
| 4870 } | 4884 } |
| 4871 | 4885 |
| 4872 | 4886 |
| 4873 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, | 4887 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
| 4874 Handle<Name> key, | 4888 Handle<Name> key, |
| 4875 Handle<Object> value) { | 4889 Handle<Object> value) { |
| 4876 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 4890 Isolate* isolate = object->GetIsolate(); |
| 4877 obj->SetHiddenProperty(*key, *value), | 4891 |
| 4878 Object); | 4892 ASSERT(key->IsUniqueName()); |
| 4893 if (object->IsJSGlobalProxy()) { | |
| 4894 // For a proxy, use the prototype as target object. | |
| 4895 Handle<Object> proxy_parent(object->GetPrototype(), isolate); | |
| 4896 // If the proxy is detached, return undefined. | |
| 4897 if (proxy_parent->IsNull()) return isolate->factory()->undefined_value(); | |
| 4898 ASSERT(proxy_parent->IsJSGlobalObject()); | |
| 4899 return JSObject::SetHiddenProperty(Handle<JSObject>::cast(proxy_parent), | |
| 4900 key, | |
| 4901 value); | |
| 4902 } | |
| 4903 ASSERT(!object->IsJSGlobalProxy()); | |
| 4904 | |
| 4905 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | |
| 4906 | |
| 4907 // If there is no backing store yet, store the identity hash inline. | |
| 4908 if (value->IsSmi() && | |
| 4909 *key == *isolate->factory()->identity_hash_string() && | |
| 4910 (inline_value->IsUndefined() || inline_value->IsSmi())) { | |
| 4911 return JSObject::SetHiddenPropertiesHashTable(object, value); | |
| 4912 } | |
| 4913 | |
| 4914 Handle<ObjectHashTable> hashtable = | |
| 4915 JSObject::GetOrCreateHiddenPropertiesHashtable(object); | |
| 4916 | |
| 4917 // If it was found, check if the key is already in the dictionary. | |
| 4918 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, | |
| 4919 value); | |
| 4920 if (*new_table != *hashtable) { | |
| 4921 // If adding the key expanded the dictionary (i.e., Add returned a new | |
| 4922 // dictionary), store it back to the object. | |
| 4923 JSObject::SetHiddenPropertiesHashTable(object, new_table); | |
| 4924 } | |
| 4925 | |
| 4926 // Return this to mark success. | |
| 4927 return object; | |
| 4879 } | 4928 } |
| 4880 | 4929 |
| 4881 | 4930 |
| 4882 MaybeObject* JSObject::SetHiddenProperty(Name* key, Object* value) { | |
| 4883 ASSERT(key->IsUniqueName()); | |
| 4884 if (IsJSGlobalProxy()) { | |
| 4885 // For a proxy, use the prototype as target object. | |
| 4886 Object* proxy_parent = GetPrototype(); | |
| 4887 // If the proxy is detached, return undefined. | |
| 4888 if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); | |
| 4889 ASSERT(proxy_parent->IsJSGlobalObject()); | |
| 4890 return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value); | |
| 4891 } | |
| 4892 ASSERT(!IsJSGlobalProxy()); | |
| 4893 MaybeObject* hidden_lookup = | |
| 4894 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); | |
| 4895 Object* inline_value = hidden_lookup->ToObjectUnchecked(); | |
| 4896 | |
| 4897 // If there is no backing store yet, store the identity hash inline. | |
| 4898 if (value->IsSmi() && | |
| 4899 key == GetHeap()->identity_hash_string() && | |
| 4900 (inline_value->IsUndefined() || inline_value->IsSmi())) { | |
| 4901 return SetHiddenPropertiesHashTable(value); | |
| 4902 } | |
| 4903 | |
| 4904 hidden_lookup = GetHiddenPropertiesHashTable(CREATE_NEW_IF_ABSENT); | |
| 4905 ObjectHashTable* hashtable; | |
| 4906 if (!hidden_lookup->To(&hashtable)) return hidden_lookup; | |
| 4907 | |
| 4908 // If it was found, check if the key is already in the dictionary. | |
| 4909 MaybeObject* insert_result = hashtable->Put(key, value); | |
| 4910 ObjectHashTable* new_table; | |
| 4911 if (!insert_result->To(&new_table)) return insert_result; | |
| 4912 if (new_table != hashtable) { | |
| 4913 // If adding the key expanded the dictionary (i.e., Add returned a new | |
| 4914 // dictionary), store it back to the object. | |
| 4915 MaybeObject* store_result = SetHiddenPropertiesHashTable(new_table); | |
| 4916 if (store_result->IsFailure()) return store_result; | |
| 4917 } | |
| 4918 // Return this to mark success. | |
| 4919 return this; | |
| 4920 } | |
| 4921 | |
| 4922 | |
| 4923 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { | 4931 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { |
| 4924 Isolate* isolate = object->GetIsolate(); | 4932 Isolate* isolate = object->GetIsolate(); |
| 4925 ASSERT(key->IsUniqueName()); | 4933 ASSERT(key->IsUniqueName()); |
| 4926 | 4934 |
| 4927 if (object->IsJSGlobalProxy()) { | 4935 if (object->IsJSGlobalProxy()) { |
| 4928 Handle<Object> proto(object->GetPrototype(), isolate); | 4936 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4929 if (proto->IsNull()) return; | 4937 if (proto->IsNull()) return; |
| 4930 ASSERT(proto->IsJSGlobalObject()); | 4938 ASSERT(proto->IsJSGlobalObject()); |
| 4931 return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key); | 4939 return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key); |
| 4932 } | 4940 } |
| 4933 | 4941 |
| 4934 MaybeObject* hidden_lookup = | 4942 Object* inline_value = object->GetHiddenPropertiesHashTable(); |
| 4935 object->GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); | |
| 4936 Object* inline_value = hidden_lookup->ToObjectUnchecked(); | |
| 4937 | 4943 |
| 4938 // We never delete (inline-stored) identity hashes. | 4944 // We never delete (inline-stored) identity hashes. |
| 4939 ASSERT(*key != isolate->heap()->identity_hash_string()); | 4945 ASSERT(*key != *isolate->factory()->identity_hash_string()); |
| 4940 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; | 4946 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; |
| 4941 | 4947 |
| 4942 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 4948 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
| 4943 PutIntoObjectHashTable(hashtable, key, isolate->factory()->the_hole_value()); | 4949 ObjectHashTable::Put(hashtable, key, isolate->factory()->the_hole_value()); |
| 4944 } | 4950 } |
| 4945 | 4951 |
| 4946 | 4952 |
| 4947 bool JSObject::HasHiddenProperties() { | 4953 bool JSObject::HasHiddenProperties() { |
| 4948 return GetPropertyAttributePostInterceptor(this, | 4954 return GetPropertyAttributePostInterceptor(this, |
| 4949 GetHeap()->hidden_string(), | 4955 GetHeap()->hidden_string(), |
| 4950 false) != ABSENT; | 4956 false) != ABSENT; |
| 4951 } | 4957 } |
| 4952 | 4958 |
| 4953 | 4959 |
| 4954 MaybeObject* JSObject::GetHiddenPropertiesHashTable( | 4960 Object* JSObject::GetHiddenPropertiesHashTable() { |
| 4955 InitializeHiddenProperties init_option) { | |
| 4956 ASSERT(!IsJSGlobalProxy()); | 4961 ASSERT(!IsJSGlobalProxy()); |
| 4957 Object* inline_value; | 4962 Object* inline_value; |
|
Michael Starzinger
2013/11/04 17:58:58
nit: The local "inline_value" variable is (almost)
rafaelw
2013/11/05 09:56:54
Done.
| |
| 4958 if (HasFastProperties()) { | 4963 if (HasFastProperties()) { |
| 4959 // If the object has fast properties, check whether the first slot | 4964 // If the object has fast properties, check whether the first slot |
| 4960 // in the descriptor array matches the hidden string. Since the | 4965 // in the descriptor array matches the hidden string. Since the |
| 4961 // hidden strings hash code is zero (and no other name has hash | 4966 // hidden strings hash code is zero (and no other name has hash |
| 4962 // code zero) it will always occupy the first entry if present. | 4967 // code zero) it will always occupy the first entry if present. |
| 4963 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 4968 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 4964 if (descriptors->number_of_descriptors() > 0) { | 4969 if (descriptors->number_of_descriptors() > 0) { |
| 4965 int sorted_index = descriptors->GetSortedKeyIndex(0); | 4970 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 4966 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 4971 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && |
| 4967 sorted_index < map()->NumberOfOwnDescriptors()) { | 4972 sorted_index < map()->NumberOfOwnDescriptors()) { |
| 4968 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 4973 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 4969 ASSERT(descriptors->GetDetails(sorted_index).representation(). | 4974 ASSERT(descriptors->GetDetails(sorted_index).representation(). |
| 4970 IsCompatibleForLoad(Representation::Tagged())); | 4975 IsCompatibleForLoad(Representation::Tagged())); |
| 4971 inline_value = this->RawFastPropertyAt( | 4976 inline_value = this->RawFastPropertyAt( |
| 4972 descriptors->GetFieldIndex(sorted_index)); | 4977 descriptors->GetFieldIndex(sorted_index)); |
| 4978 return inline_value; | |
| 4973 } else { | 4979 } else { |
| 4974 inline_value = GetHeap()->undefined_value(); | 4980 return GetHeap()->undefined_value(); |
| 4975 } | 4981 } |
| 4976 } else { | 4982 } else { |
| 4977 inline_value = GetHeap()->undefined_value(); | 4983 return GetHeap()->undefined_value(); |
| 4978 } | 4984 } |
| 4979 } else { | 4985 } else { |
| 4980 PropertyAttributes attributes; | 4986 PropertyAttributes attributes; |
| 4981 // You can't install a getter on a property indexed by the hidden string, | 4987 // You can't install a getter on a property indexed by the hidden string, |
| 4982 // so we can be sure that GetLocalPropertyPostInterceptor returns a real | 4988 // so we can be sure that GetLocalPropertyPostInterceptor returns a real |
| 4983 // object. | 4989 // object. |
| 4984 inline_value = | 4990 return GetLocalPropertyPostInterceptor(this, |
| 4985 GetLocalPropertyPostInterceptor(this, | 4991 GetHeap()->hidden_string(), |
| 4986 GetHeap()->hidden_string(), | 4992 &attributes)->ToObjectUnchecked(); |
| 4987 &attributes)->ToObjectUnchecked(); | 4993 } |
| 4994 } | |
| 4995 | |
| 4996 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable( | |
| 4997 Handle<JSObject> object) { | |
| 4998 Isolate* isolate = object->GetIsolate(); | |
| 4999 | |
| 5000 static const int kInitialCapacity = 4; | |
| 5001 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | |
| 5002 if (inline_value->IsHashTable()) { | |
| 5003 return Handle<ObjectHashTable>::cast(inline_value); | |
| 4988 } | 5004 } |
| 4989 | 5005 |
| 4990 if (init_option == ONLY_RETURN_INLINE_VALUE || | 5006 Handle<ObjectHashTable> hashtable = isolate->factory()->NewObjectHashTable( |
| 4991 inline_value->IsHashTable()) { | 5007 kInitialCapacity, |
| 4992 return inline_value; | 5008 USE_CUSTOM_MINIMUM_CAPACITY); |
| 4993 } | |
| 4994 | |
| 4995 ObjectHashTable* hashtable; | |
| 4996 static const int kInitialCapacity = 4; | |
| 4997 MaybeObject* maybe_obj = | |
| 4998 ObjectHashTable::Allocate(GetHeap(), | |
| 4999 kInitialCapacity, | |
| 5000 ObjectHashTable::USE_CUSTOM_MINIMUM_CAPACITY); | |
| 5001 if (!maybe_obj->To<ObjectHashTable>(&hashtable)) return maybe_obj; | |
| 5002 | 5009 |
| 5003 if (inline_value->IsSmi()) { | 5010 if (inline_value->IsSmi()) { |
| 5004 // We were storing the identity hash inline and now allocated an actual | 5011 // We were storing the identity hash inline and now allocated an actual |
| 5005 // dictionary. Put the identity hash into the new dictionary. | 5012 // dictionary. Put the identity hash into the new dictionary. |
| 5006 MaybeObject* insert_result = | 5013 hashtable = ObjectHashTable::Put(hashtable, |
| 5007 hashtable->Put(GetHeap()->identity_hash_string(), inline_value); | 5014 isolate->factory()->identity_hash_string(), |
| 5008 ObjectHashTable* new_table; | 5015 inline_value); |
| 5009 if (!insert_result->To(&new_table)) return insert_result; | |
| 5010 // We expect no resizing for the first insert. | |
| 5011 ASSERT_EQ(hashtable, new_table); | |
| 5012 } | 5016 } |
| 5013 | 5017 |
| 5014 MaybeObject* store_result = SetLocalPropertyIgnoreAttributesTrampoline( | 5018 JSObject::SetLocalPropertyIgnoreAttributes( |
| 5015 GetHeap()->hidden_string(), | 5019 object, |
| 5020 isolate->factory()->hidden_string(), | |
| 5016 hashtable, | 5021 hashtable, |
| 5017 DONT_ENUM, | 5022 DONT_ENUM, |
| 5018 OPTIMAL_REPRESENTATION, | 5023 OPTIMAL_REPRESENTATION, |
| 5019 ALLOW_AS_CONSTANT, | 5024 ALLOW_AS_CONSTANT, |
| 5020 OMIT_EXTENSIBILITY_CHECK); | 5025 OMIT_EXTENSIBILITY_CHECK); |
| 5021 if (store_result->IsFailure()) return store_result; | 5026 |
| 5022 return hashtable; | 5027 return hashtable; |
| 5023 } | 5028 } |
| 5024 | 5029 |
| 5025 | 5030 |
| 5026 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { | 5031 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
| 5027 ASSERT(!IsJSGlobalProxy()); | 5032 Handle<Object> value) { |
| 5033 ASSERT(!object->IsJSGlobalProxy()); | |
| 5034 | |
| 5035 Isolate* isolate = object->GetIsolate(); | |
| 5036 | |
| 5028 // We can store the identity hash inline iff there is no backing store | 5037 // We can store the identity hash inline iff there is no backing store |
| 5029 // for hidden properties yet. | 5038 // for hidden properties yet. |
| 5030 ASSERT(HasHiddenProperties() != value->IsSmi()); | 5039 ASSERT(object->HasHiddenProperties() != value->IsSmi()); |
| 5031 if (HasFastProperties()) { | 5040 if (object->HasFastProperties()) { |
| 5032 // If the object has fast properties, check whether the first slot | 5041 // If the object has fast properties, check whether the first slot |
| 5033 // in the descriptor array matches the hidden string. Since the | 5042 // in the descriptor array matches the hidden string. Since the |
| 5034 // hidden strings hash code is zero (and no other name has hash | 5043 // hidden strings hash code is zero (and no other name has hash |
| 5035 // code zero) it will always occupy the first entry if present. | 5044 // code zero) it will always occupy the first entry if present. |
| 5036 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 5045 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 5037 if (descriptors->number_of_descriptors() > 0) { | 5046 if (descriptors->number_of_descriptors() > 0) { |
| 5038 int sorted_index = descriptors->GetSortedKeyIndex(0); | 5047 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 5039 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 5048 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string() |
| 5040 sorted_index < map()->NumberOfOwnDescriptors()) { | 5049 && sorted_index < object->map()->NumberOfOwnDescriptors()) { |
| 5041 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 5050 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 5042 FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value); | 5051 object->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), |
| 5043 return this; | 5052 *value); |
| 5053 return object; | |
| 5044 } | 5054 } |
| 5045 } | 5055 } |
| 5046 } | 5056 } |
| 5047 MaybeObject* store_result = SetLocalPropertyIgnoreAttributesTrampoline( | 5057 |
| 5048 GetHeap()->hidden_string(), | 5058 JSObject::SetLocalPropertyIgnoreAttributes( |
| 5059 object, | |
| 5060 isolate->factory()->hidden_string(), | |
| 5049 value, | 5061 value, |
| 5050 DONT_ENUM, | 5062 DONT_ENUM, |
| 5051 OPTIMAL_REPRESENTATION, | 5063 OPTIMAL_REPRESENTATION, |
| 5052 ALLOW_AS_CONSTANT, | 5064 ALLOW_AS_CONSTANT, |
| 5053 OMIT_EXTENSIBILITY_CHECK); | 5065 OMIT_EXTENSIBILITY_CHECK); |
| 5054 if (store_result->IsFailure()) return store_result; | 5066 return object; |
| 5055 return this; | |
| 5056 } | 5067 } |
| 5057 | 5068 |
| 5058 | 5069 |
| 5059 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, | 5070 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, |
| 5060 Handle<Name> name, | 5071 Handle<Name> name, |
| 5061 DeleteMode mode) { | 5072 DeleteMode mode) { |
| 5062 // Check local property, ignore interceptor. | 5073 // Check local property, ignore interceptor. |
| 5063 Isolate* isolate = object->GetIsolate(); | 5074 Isolate* isolate = object->GetIsolate(); |
| 5064 LookupResult result(isolate); | 5075 LookupResult result(isolate); |
| 5065 object->LocalLookupRealNamedProperty(*name, &result); | 5076 object->LocalLookupRealNamedProperty(*name, &result); |
| (...skipping 10065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15131 | 15142 |
| 15132 template<typename Shape, typename Key> | 15143 template<typename Shape, typename Key> |
| 15133 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, | 15144 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, |
| 15134 int at_least_space_for, | 15145 int at_least_space_for, |
| 15135 PretenureFlag pretenure) { | 15146 PretenureFlag pretenure) { |
| 15136 Object* obj; | 15147 Object* obj; |
| 15137 { MaybeObject* maybe_obj = | 15148 { MaybeObject* maybe_obj = |
| 15138 HashTable<Shape, Key>::Allocate( | 15149 HashTable<Shape, Key>::Allocate( |
| 15139 heap, | 15150 heap, |
| 15140 at_least_space_for, | 15151 at_least_space_for, |
| 15141 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY, | 15152 USE_DEFAULT_MINIMUM_CAPACITY, |
| 15142 pretenure); | 15153 pretenure); |
| 15143 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15154 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 15144 } | 15155 } |
| 15145 // Initialize the next enumeration index. | 15156 // Initialize the next enumeration index. |
| 15146 Dictionary<Shape, Key>::cast(obj)-> | 15157 Dictionary<Shape, Key>::cast(obj)-> |
| 15147 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 15158 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 15148 return obj; | 15159 return obj; |
| 15149 } | 15160 } |
| 15150 | 15161 |
| 15151 | 15162 |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15697 obj->set_properties(fields); | 15708 obj->set_properties(fields); |
| 15698 ASSERT(obj->IsJSObject()); | 15709 ASSERT(obj->IsJSObject()); |
| 15699 | 15710 |
| 15700 // Check that it really works. | 15711 // Check that it really works. |
| 15701 ASSERT(obj->HasFastProperties()); | 15712 ASSERT(obj->HasFastProperties()); |
| 15702 | 15713 |
| 15703 return obj; | 15714 return obj; |
| 15704 } | 15715 } |
| 15705 | 15716 |
| 15706 | 15717 |
| 15718 Handle<ObjectHashSet> ObjectHashSet::EnsureCapacity( | |
| 15719 Handle<ObjectHashSet> table, | |
| 15720 int n, | |
| 15721 Handle<Object> key, | |
| 15722 PretenureFlag pretenure) { | |
| 15723 Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table; | |
| 15724 CALL_HEAP_FUNCTION(table_base->GetIsolate(), | |
| 15725 table_base->EnsureCapacity(n, *key, pretenure), | |
| 15726 ObjectHashSet); | |
| 15727 } | |
| 15728 | |
| 15729 | |
| 15730 Handle<ObjectHashSet> ObjectHashSet::Shrink(Handle<ObjectHashSet> table, | |
| 15731 Handle<Object> key) { | |
| 15732 Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table; | |
| 15733 CALL_HEAP_FUNCTION(table_base->GetIsolate(), | |
| 15734 table_base->Shrink(*key), | |
| 15735 ObjectHashSet); | |
| 15736 } | |
| 15737 | |
| 15738 | |
| 15707 bool ObjectHashSet::Contains(Object* key) { | 15739 bool ObjectHashSet::Contains(Object* key) { |
| 15708 ASSERT(IsKey(key)); | 15740 ASSERT(IsKey(key)); |
| 15709 | 15741 |
| 15710 // If the object does not have an identity hash, it was never used as a key. | 15742 // If the object does not have an identity hash, it was never used as a key. |
| 15711 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); | 15743 Object* hash = key->GetHash(); |
| 15712 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false; | 15744 if (hash->IsUndefined()) return false; |
| 15713 } | 15745 |
| 15714 return (FindEntry(key) != kNotFound); | 15746 return (FindEntry(key) != kNotFound); |
| 15715 } | 15747 } |
| 15716 | 15748 |
| 15717 | 15749 |
| 15718 MaybeObject* ObjectHashSet::Add(Object* key) { | 15750 Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> table, |
| 15719 ASSERT(IsKey(key)); | 15751 Handle<Object> key) { |
| 15752 ASSERT(table->IsKey(*key)); | |
| 15720 | 15753 |
| 15721 // Make sure the key object has an identity hash code. | 15754 // Make sure the key object has an identity hash code. |
| 15722 int hash; | 15755 Handle<Object> object_hash = Object::GetOrCreateHash(key, |
| 15723 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); | 15756 table->GetIsolate()); |
| 15724 if (maybe_hash->IsFailure()) return maybe_hash; | 15757 |
| 15725 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); | 15758 int entry = table->FindEntry(*key); |
| 15726 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | |
| 15727 } | |
| 15728 int entry = FindEntry(key); | |
| 15729 | 15759 |
| 15730 // Check whether key is already present. | 15760 // Check whether key is already present. |
| 15731 if (entry != kNotFound) return this; | 15761 if (entry != kNotFound) return table; |
| 15732 | 15762 |
| 15733 // Check whether the hash set should be extended and add entry. | 15763 // Check whether the hash set should be extended and add entry. |
| 15734 Object* obj; | 15764 Handle<ObjectHashSet> new_table = |
| 15735 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 15765 ObjectHashSet::EnsureCapacity(table, 1, key); |
| 15736 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15766 entry = new_table->FindInsertionEntry(Smi::cast(*object_hash)->value()); |
| 15737 } | 15767 new_table->set(ObjectHashSet::EntryToIndex(entry), *key); |
| 15738 ObjectHashSet* table = ObjectHashSet::cast(obj); | 15768 new_table->ElementAdded(); |
| 15739 entry = table->FindInsertionEntry(hash); | 15769 return new_table; |
| 15740 table->set(EntryToIndex(entry), key); | |
| 15741 table->ElementAdded(); | |
| 15742 return table; | |
| 15743 } | 15770 } |
| 15744 | 15771 |
| 15745 | 15772 |
| 15746 MaybeObject* ObjectHashSet::Remove(Object* key) { | 15773 Handle<ObjectHashSet> ObjectHashSet::Remove(Handle<ObjectHashSet> table, |
| 15747 ASSERT(IsKey(key)); | 15774 Handle<Object> key) { |
| 15775 ASSERT(table->IsKey(*key)); | |
| 15748 | 15776 |
| 15749 // If the object does not have an identity hash, it was never used as a key. | 15777 // If the object does not have an identity hash, it was never used as a key. |
| 15750 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); | 15778 if (key->GetHash()->IsUndefined()) return table; |
| 15751 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this; | 15779 |
| 15752 } | 15780 int entry = table->FindEntry(*key); |
| 15753 int entry = FindEntry(key); | |
| 15754 | 15781 |
| 15755 // Check whether key is actually present. | 15782 // Check whether key is actually present. |
| 15756 if (entry == kNotFound) return this; | 15783 if (entry == kNotFound) return table; |
| 15757 | 15784 |
| 15758 // Remove entry and try to shrink this hash set. | 15785 // Remove entry and try to shrink this hash set. |
| 15759 set_the_hole(EntryToIndex(entry)); | 15786 table->set_the_hole(ObjectHashSet::EntryToIndex(entry)); |
| 15760 ElementRemoved(); | 15787 table->ElementRemoved(); |
| 15761 return Shrink(key); | 15788 |
| 15789 return ObjectHashSet::Shrink(table, key); | |
| 15762 } | 15790 } |
| 15763 | 15791 |
| 15764 | 15792 |
| 15793 Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity( | |
| 15794 Handle<ObjectHashTable> table, | |
| 15795 int n, | |
| 15796 Handle<Object> key, | |
| 15797 PretenureFlag pretenure) { | |
| 15798 Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table; | |
| 15799 CALL_HEAP_FUNCTION(table_base->GetIsolate(), | |
| 15800 table_base->EnsureCapacity(n, *key, pretenure), | |
| 15801 ObjectHashTable); | |
| 15802 } | |
| 15803 | |
| 15804 | |
| 15805 Handle<ObjectHashTable> ObjectHashTable::Shrink( | |
| 15806 Handle<ObjectHashTable> table, Handle<Object> key) { | |
| 15807 Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table; | |
| 15808 CALL_HEAP_FUNCTION(table_base->GetIsolate(), | |
| 15809 table_base->Shrink(*key), | |
| 15810 ObjectHashTable); | |
| 15811 } | |
| 15812 | |
| 15813 | |
| 15765 Object* ObjectHashTable::Lookup(Object* key) { | 15814 Object* ObjectHashTable::Lookup(Object* key) { |
| 15766 ASSERT(IsKey(key)); | 15815 ASSERT(IsKey(key)); |
| 15767 | 15816 |
| 15768 // If the object does not have an identity hash, it was never used as a key. | 15817 // If the object does not have an identity hash, it was never used as a key. |
| 15769 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); | 15818 Object* hash = key->GetHash(); |
| 15770 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) { | 15819 if (hash->IsUndefined()) { |
| 15771 return GetHeap()->the_hole_value(); | 15820 return GetHeap()->the_hole_value(); |
| 15772 } | |
| 15773 } | 15821 } |
| 15774 int entry = FindEntry(key); | 15822 int entry = FindEntry(key); |
| 15775 if (entry == kNotFound) return GetHeap()->the_hole_value(); | 15823 if (entry == kNotFound) return GetHeap()->the_hole_value(); |
| 15776 return get(EntryToIndex(entry) + 1); | 15824 return get(EntryToIndex(entry) + 1); |
| 15777 } | 15825 } |
| 15778 | 15826 |
| 15779 | 15827 |
| 15780 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { | 15828 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
| 15781 ASSERT(IsKey(key)); | 15829 Handle<Object> key, |
| 15830 Handle<Object> value) { | |
| 15831 ASSERT(table->IsKey(*key)); | |
| 15832 | |
| 15833 Isolate* isolate = table->GetIsolate(); | |
| 15782 | 15834 |
| 15783 // Make sure the key object has an identity hash code. | 15835 // Make sure the key object has an identity hash code. |
| 15784 int hash; | 15836 Handle<Object> hash = Object::GetOrCreateHash(key, isolate); |
| 15785 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); | 15837 |
| 15786 if (maybe_hash->IsFailure()) return maybe_hash; | 15838 int entry = table->FindEntry(*key); |
| 15787 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); | |
| 15788 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | |
| 15789 } | |
| 15790 int entry = FindEntry(key); | |
| 15791 | 15839 |
| 15792 // Check whether to perform removal operation. | 15840 // Check whether to perform removal operation. |
| 15793 if (value->IsTheHole()) { | 15841 if (value->IsTheHole()) { |
| 15794 if (entry == kNotFound) return this; | 15842 if (entry == kNotFound) return table; |
| 15795 RemoveEntry(entry); | 15843 table->RemoveEntry(entry); |
| 15796 return Shrink(key); | 15844 return ObjectHashTable::Shrink(table, key); |
| 15797 } | 15845 } |
| 15798 | 15846 |
| 15799 // Key is already in table, just overwrite value. | 15847 // Key is already in table, just overwrite value. |
| 15800 if (entry != kNotFound) { | 15848 if (entry != kNotFound) { |
| 15801 set(EntryToIndex(entry) + 1, value); | 15849 table->set(ObjectHashTable::EntryToIndex(entry) + 1, *value); |
| 15802 return this; | 15850 return table; |
| 15803 } | 15851 } |
| 15804 | 15852 |
| 15805 // Check whether the hash table should be extended. | 15853 // Check whether the hash table should be extended. |
| 15806 Object* obj; | 15854 table = ObjectHashTable::EnsureCapacity(table, 1, key); |
| 15807 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 15855 table->AddEntry(table->FindInsertionEntry(Handle<Smi>::cast(hash)->value()), |
| 15808 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15856 *key, |
| 15809 } | 15857 *value); |
| 15810 ObjectHashTable* table = ObjectHashTable::cast(obj); | |
| 15811 table->AddEntry(table->FindInsertionEntry(hash), key, value); | |
| 15812 return table; | 15858 return table; |
| 15813 } | 15859 } |
| 15814 | 15860 |
| 15815 | 15861 |
| 15816 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { | 15862 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { |
| 15817 set(EntryToIndex(entry), key); | 15863 set(EntryToIndex(entry), key); |
| 15818 set(EntryToIndex(entry) + 1, value); | 15864 set(EntryToIndex(entry) + 1, value); |
| 15819 ElementAdded(); | 15865 ElementAdded(); |
| 15820 } | 15866 } |
| 15821 | 15867 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16396 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16442 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16397 static const char* error_messages_[] = { | 16443 static const char* error_messages_[] = { |
| 16398 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16444 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16399 }; | 16445 }; |
| 16400 #undef ERROR_MESSAGES_TEXTS | 16446 #undef ERROR_MESSAGES_TEXTS |
| 16401 return error_messages_[reason]; | 16447 return error_messages_[reason]; |
| 16402 } | 16448 } |
| 16403 | 16449 |
| 16404 | 16450 |
| 16405 } } // namespace v8::internal | 16451 } } // namespace v8::internal |
| OLD | NEW |