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

Side by Side Diff: src/objects.cc

Issue 153923005: A64: Synchronize with r17525. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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());
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 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after
2142 AddSlowProperty(object, name, value, attributes); 2150 AddSlowProperty(object, name, value, attributes);
2143 } 2151 }
2144 } else { 2152 } else {
2145 AddSlowProperty(object, name, value, attributes); 2153 AddSlowProperty(object, name, value, attributes);
2146 } 2154 }
2147 2155
2148 if (FLAG_harmony_observation && 2156 if (FLAG_harmony_observation &&
2149 object->map()->is_observed() && 2157 object->map()->is_observed() &&
2150 *name != isolate->heap()->hidden_string()) { 2158 *name != isolate->heap()->hidden_string()) {
2151 Handle<Object> old_value = isolate->factory()->the_hole_value(); 2159 Handle<Object> old_value = isolate->factory()->the_hole_value();
2152 EnqueueChangeRecord(object, "new", name, old_value); 2160 EnqueueChangeRecord(object, "add", name, old_value);
2153 } 2161 }
2154 2162
2155 return value; 2163 return value;
2156 } 2164 }
2157 2165
2158 2166
2159 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, 2167 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
2160 const char* type_str, 2168 const char* type_str,
2161 Handle<Name> name, 2169 Handle<Name> name,
2162 Handle<Object> old_value) { 2170 Handle<Object> old_value) {
2163 Isolate* isolate = object->GetIsolate(); 2171 Isolate* isolate = object->GetIsolate();
2164 HandleScope scope(isolate); 2172 HandleScope scope(isolate);
2165 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); 2173 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
2166 if (object->IsJSGlobalObject()) { 2174 if (object->IsJSGlobalObject()) {
2167 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); 2175 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate);
2168 } 2176 }
2169 Handle<Object> args[] = { type, object, name, old_value }; 2177 Handle<Object> args[] = { type, object, name, old_value };
2178 int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
2170 bool threw; 2179 bool threw;
2180
2171 Execution::Call(isolate, 2181 Execution::Call(isolate,
2172 Handle<JSFunction>(isolate->observers_notify_change()), 2182 Handle<JSFunction>(isolate->observers_notify_change()),
2173 isolate->factory()->undefined_value(), 2183 isolate->factory()->undefined_value(),
2174 old_value->IsTheHole() ? 3 : 4, args, 2184 argc, args,
2175 &threw); 2185 &threw);
2176 ASSERT(!threw); 2186 ASSERT(!threw);
2177 } 2187 }
2178 2188
2179 2189
2180 void JSObject::DeliverChangeRecords(Isolate* isolate) { 2190 void JSObject::DeliverChangeRecords(Isolate* isolate) {
2181 ASSERT(isolate->observer_delivery_pending()); 2191 ASSERT(isolate->observer_delivery_pending());
2182 bool threw = false; 2192 bool threw = false;
2183 Execution::Call( 2193 Execution::Call(
2184 isolate, 2194 isolate,
(...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after
3748 Handle<JSReceiver> receiver(receiver_raw); 3758 Handle<JSReceiver> receiver(receiver_raw);
3749 Handle<String> name = isolate->factory()->Uint32ToString(index); 3759 Handle<String> name = isolate->factory()->Uint32ToString(index);
3750 return proxy->GetPropertyAttributeWithHandler(*receiver, *name); 3760 return proxy->GetPropertyAttributeWithHandler(*receiver, *name);
3751 } 3761 }
3752 3762
3753 3763
3754 void JSProxy::Fix(Handle<JSProxy> proxy) { 3764 void JSProxy::Fix(Handle<JSProxy> proxy) {
3755 Isolate* isolate = proxy->GetIsolate(); 3765 Isolate* isolate = proxy->GetIsolate();
3756 3766
3757 // Save identity hash. 3767 // Save identity hash.
3758 Handle<Object> hash = JSProxy::GetIdentityHash(proxy, OMIT_CREATION); 3768 Handle<Object> hash(proxy->GetIdentityHash(), isolate);
3759 3769
3760 if (proxy->IsJSFunctionProxy()) { 3770 if (proxy->IsJSFunctionProxy()) {
3761 isolate->factory()->BecomeJSFunction(proxy); 3771 isolate->factory()->BecomeJSFunction(proxy);
3762 // Code will be set on the JavaScript side. 3772 // Code will be set on the JavaScript side.
3763 } else { 3773 } else {
3764 isolate->factory()->BecomeJSObject(proxy); 3774 isolate->factory()->BecomeJSObject(proxy);
3765 } 3775 }
3766 ASSERT(proxy->IsJSObject()); 3776 ASSERT(proxy->IsJSObject());
3767 3777
3768 // Inherit identity, if it was present. 3778 // Inherit identity, if it was present.
3769 if (hash->IsSmi()) { 3779 if (hash->IsSmi()) {
3770 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), Smi::cast(*hash)); 3780 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy),
3781 Handle<Smi>::cast(hash));
3771 } 3782 }
3772 } 3783 }
3773 3784
3774 3785
3775 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, 3786 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
3776 Handle<Object> derived, 3787 Handle<Object> derived,
3777 int argc, 3788 int argc,
3778 Handle<Object> argv[]) { 3789 Handle<Object> argv[]) {
3779 Isolate* isolate = GetIsolate(); 3790 Isolate* isolate = GetIsolate();
3780 Handle<Object> handler(this->handler(), isolate); 3791 Handle<Object> handler(this->handler(), isolate);
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
4087 break; 4098 break;
4088 case HANDLER: 4099 case HANDLER:
4089 case NONEXISTENT: 4100 case NONEXISTENT:
4090 UNREACHABLE(); 4101 UNREACHABLE();
4091 } 4102 }
4092 4103
4093 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); 4104 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
4094 4105
4095 if (is_observed) { 4106 if (is_observed) {
4096 if (lookup->IsTransition()) { 4107 if (lookup->IsTransition()) {
4097 EnqueueChangeRecord(object, "new", name, old_value); 4108 EnqueueChangeRecord(object, "add", name, old_value);
4098 } else { 4109 } else {
4099 LookupResult new_lookup(isolate); 4110 LookupResult new_lookup(isolate);
4100 object->LocalLookup(*name, &new_lookup, true); 4111 object->LocalLookup(*name, &new_lookup, true);
4101 if (new_lookup.IsDataProperty()) { 4112 if (new_lookup.IsDataProperty()) {
4102 Handle<Object> new_value = Object::GetProperty(object, name); 4113 Handle<Object> new_value = Object::GetProperty(object, name);
4103 if (!new_value->SameValue(*old_value)) { 4114 if (!new_value->SameValue(*old_value)) {
4104 EnqueueChangeRecord(object, "updated", name, old_value); 4115 EnqueueChangeRecord(object, "update", name, old_value);
4105 } 4116 }
4106 } 4117 }
4107 } 4118 }
4108 } 4119 }
4109 4120
4110 return result; 4121 return result;
4111 } 4122 }
4112 4123
4113 4124
4114 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline(
4115 Name* key,
4116 Object* value,
4117 PropertyAttributes attributes,
4118 ValueType value_type,
4119 StoreMode mode,
4120 ExtensibilityCheck extensibility_check) {
4121 // TODO(mstarzinger): The trampoline is a giant hack, don't use it anywhere
4122 // else or handlification people will start hating you for all eternity.
4123 HandleScope scope(GetIsolate());
4124 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate());
4125 return trampoline.CallWithReturnValue(
4126 &JSObject::SetLocalPropertyIgnoreAttributes,
4127 Handle<JSObject>(this),
4128 Handle<Name>(key),
4129 Handle<Object>(value, GetIsolate()),
4130 attributes,
4131 value_type,
4132 mode,
4133 extensibility_check);
4134 }
4135
4136
4137 // Set a real local property, even if it is READ_ONLY. If the property is not 4125 // Set a real local property, even if it is READ_ONLY. If the property is not
4138 // present, add it with attributes NONE. This code is an exact clone of 4126 // present, add it with attributes NONE. This code is an exact clone of
4139 // SetProperty, with the check for IsReadOnly and the check for a 4127 // SetProperty, with the check for IsReadOnly and the check for a
4140 // callback setter removed. The two lines looking up the LookupResult 4128 // callback setter removed. The two lines looking up the LookupResult
4141 // result are also added. If one of the functions is changed, the other 4129 // result are also added. If one of the functions is changed, the other
4142 // should be. 4130 // should be.
4143 // Note that this method cannot be used to set the prototype of a function 4131 // Note that this method cannot be used to set the prototype of a function
4144 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" 4132 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
4145 // doesn't handle function prototypes correctly. 4133 // doesn't handle function prototypes correctly.
4146 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( 4134 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
4227 break; 4215 break;
4228 } 4216 }
4229 case NONEXISTENT: 4217 case NONEXISTENT:
4230 case HANDLER: 4218 case HANDLER:
4231 case INTERCEPTOR: 4219 case INTERCEPTOR:
4232 UNREACHABLE(); 4220 UNREACHABLE();
4233 } 4221 }
4234 4222
4235 if (is_observed) { 4223 if (is_observed) {
4236 if (lookup.IsTransition()) { 4224 if (lookup.IsTransition()) {
4237 EnqueueChangeRecord(object, "new", name, old_value); 4225 EnqueueChangeRecord(object, "add", name, old_value);
4238 } else if (old_value->IsTheHole()) { 4226 } else if (old_value->IsTheHole()) {
4239 EnqueueChangeRecord(object, "reconfigured", name, old_value); 4227 EnqueueChangeRecord(object, "reconfigure", name, old_value);
4240 } else { 4228 } else {
4241 LookupResult new_lookup(isolate); 4229 LookupResult new_lookup(isolate);
4242 object->LocalLookup(*name, &new_lookup, true); 4230 object->LocalLookup(*name, &new_lookup, true);
4243 bool value_changed = false; 4231 bool value_changed = false;
4244 if (new_lookup.IsDataProperty()) { 4232 if (new_lookup.IsDataProperty()) {
4245 Handle<Object> new_value = Object::GetProperty(object, name); 4233 Handle<Object> new_value = Object::GetProperty(object, name);
4246 value_changed = !old_value->SameValue(*new_value); 4234 value_changed = !old_value->SameValue(*new_value);
4247 } 4235 }
4248 if (new_lookup.GetAttributes() != old_attributes) { 4236 if (new_lookup.GetAttributes() != old_attributes) {
4249 if (!value_changed) old_value = isolate->factory()->the_hole_value(); 4237 if (!value_changed) old_value = isolate->factory()->the_hole_value();
4250 EnqueueChangeRecord(object, "reconfigured", name, old_value); 4238 EnqueueChangeRecord(object, "reconfigure", name, old_value);
4251 } else if (value_changed) { 4239 } else if (value_changed) {
4252 EnqueueChangeRecord(object, "updated", name, old_value); 4240 EnqueueChangeRecord(object, "update", name, old_value);
4253 } 4241 }
4254 } 4242 }
4255 } 4243 }
4256 4244
4257 return value; 4245 return value;
4258 } 4246 }
4259 4247
4260 4248
4261 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 4249 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
4262 JSObject* receiver, 4250 JSObject* receiver,
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
4781 // within a smi. 4769 // within a smi.
4782 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; 4770 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4783 attempts++; 4771 attempts++;
4784 } while (hash_value == 0 && attempts < 30); 4772 } while (hash_value == 0 && attempts < 30);
4785 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 4773 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
4786 4774
4787 return Smi::FromInt(hash_value); 4775 return Smi::FromInt(hash_value);
4788 } 4776 }
4789 4777
4790 4778
4791 void JSObject::SetIdentityHash(Handle<JSObject> object, Smi* hash) { 4779 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) {
4792 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), 4780 Isolate* isolate = object->GetIsolate();
4793 object->SetHiddenProperty( 4781 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash);
4794 object->GetHeap()->identity_hash_string(), hash));
4795 } 4782 }
4796 4783
4797 4784
4798 int JSObject::GetIdentityHash(Handle<JSObject> object) { 4785 Object* JSObject::GetIdentityHash() {
4799 CALL_AND_RETRY_OR_DIE(object->GetIsolate(), 4786 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string());
4800 object->GetIdentityHash(ALLOW_CREATION), 4787 return stored_value->IsSmi() ? stored_value : GetHeap()->undefined_value();
4801 return Smi::cast(__object__)->value(),
4802 return 0);
4803 } 4788 }
4804 4789
4805 4790
4806 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { 4791 Handle<Object> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
4807 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string()); 4792 Handle<Object> hash(object->GetIdentityHash(), object->GetIsolate());
4808 if (stored_value->IsSmi()) return stored_value; 4793 if (hash->IsSmi())
4794 return hash;
4809 4795
4810 // Do not generate permanent identity hash code if not requested. 4796 Isolate* isolate = object->GetIsolate();
4811 if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
4812 4797
4813 Smi* hash = GenerateIdentityHash(); 4798 hash = handle(object->GenerateIdentityHash(), isolate);
4814 MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_string(), 4799 Handle<Object> result = SetHiddenProperty(object,
4815 hash); 4800 isolate->factory()->identity_hash_string(), hash);
4816 if (result->IsFailure()) return result; 4801
4817 if (result->ToObjectUnchecked()->IsUndefined()) { 4802 if (result->IsUndefined()) {
4818 // Trying to get hash of detached proxy. 4803 // Trying to get hash of detached proxy.
4819 return Smi::FromInt(0); 4804 return handle(Smi::FromInt(0), isolate);
4820 } 4805 }
4806
4821 return hash; 4807 return hash;
4822 } 4808 }
4823 4809
4824 4810
4825 Handle<Object> JSProxy::GetIdentityHash(Handle<JSProxy> proxy, 4811 Object* JSProxy::GetIdentityHash() {
4826 CreationFlag flag) { 4812 return this->hash();
4827 CALL_HEAP_FUNCTION(proxy->GetIsolate(), proxy->GetIdentityHash(flag), Object);
4828 } 4813 }
4829 4814
4830 4815
4831 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) { 4816 Handle<Object> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
4832 Object* hash = this->hash(); 4817 Isolate* isolate = proxy->GetIsolate();
4833 if (!hash->IsSmi() && flag == ALLOW_CREATION) { 4818
4834 hash = GenerateIdentityHash(); 4819 Handle<Object> hash(proxy->GetIdentityHash(), isolate);
4835 set_hash(hash); 4820 if (hash->IsSmi())
4836 } 4821 return hash;
4822
4823 hash = handle(proxy->GenerateIdentityHash(), isolate);
4824 proxy->set_hash(*hash);
4837 return hash; 4825 return hash;
4838 } 4826 }
4839 4827
4840 4828
4841 Object* JSObject::GetHiddenProperty(Name* key) { 4829 Object* JSObject::GetHiddenProperty(Name* key) {
4842 ASSERT(key->IsUniqueName()); 4830 ASSERT(key->IsUniqueName());
4843 if (IsJSGlobalProxy()) { 4831 if (IsJSGlobalProxy()) {
4844 // For a proxy, use the prototype as target object. 4832 // For a proxy, use the prototype as target object.
4845 Object* proxy_parent = GetPrototype(); 4833 Object* proxy_parent = GetPrototype();
4846 // If the proxy is detached, return undefined. 4834 // If the proxy is detached, return undefined.
4847 if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); 4835 if (proxy_parent->IsNull()) return GetHeap()->the_hole_value();
4848 ASSERT(proxy_parent->IsJSGlobalObject()); 4836 ASSERT(proxy_parent->IsJSGlobalObject());
4849 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); 4837 return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
4850 } 4838 }
4851 ASSERT(!IsJSGlobalProxy()); 4839 ASSERT(!IsJSGlobalProxy());
4852 MaybeObject* hidden_lookup = 4840 Object* inline_value = GetHiddenPropertiesHashTable();
4853 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
4854 Object* inline_value = hidden_lookup->ToObjectUnchecked();
4855 4841
4856 if (inline_value->IsSmi()) { 4842 if (inline_value->IsSmi()) {
4857 // Handle inline-stored identity hash. 4843 // Handle inline-stored identity hash.
4858 if (key == GetHeap()->identity_hash_string()) { 4844 if (key == GetHeap()->identity_hash_string()) {
4859 return inline_value; 4845 return inline_value;
4860 } else { 4846 } else {
4861 return GetHeap()->the_hole_value(); 4847 return GetHeap()->the_hole_value();
4862 } 4848 }
4863 } 4849 }
4864 4850
4865 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); 4851 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
4866 4852
4867 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); 4853 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
4868 Object* entry = hashtable->Lookup(key); 4854 Object* entry = hashtable->Lookup(key);
4869 return entry; 4855 return entry;
4870 } 4856 }
4871 4857
4872 4858
4873 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, 4859 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
4874 Handle<Name> key, 4860 Handle<Name> key,
4875 Handle<Object> value) { 4861 Handle<Object> value) {
4876 CALL_HEAP_FUNCTION(obj->GetIsolate(), 4862 Isolate* isolate = object->GetIsolate();
4877 obj->SetHiddenProperty(*key, *value), 4863
4878 Object); 4864 ASSERT(key->IsUniqueName());
4865 if (object->IsJSGlobalProxy()) {
4866 // For a proxy, use the prototype as target object.
4867 Handle<Object> proxy_parent(object->GetPrototype(), isolate);
4868 // If the proxy is detached, return undefined.
4869 if (proxy_parent->IsNull()) return isolate->factory()->undefined_value();
4870 ASSERT(proxy_parent->IsJSGlobalObject());
4871 return SetHiddenProperty(Handle<JSObject>::cast(proxy_parent), key, value);
4872 }
4873 ASSERT(!object->IsJSGlobalProxy());
4874
4875 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4876
4877 // If there is no backing store yet, store the identity hash inline.
4878 if (value->IsSmi() &&
4879 *key == *isolate->factory()->identity_hash_string() &&
4880 (inline_value->IsUndefined() || inline_value->IsSmi())) {
4881 return JSObject::SetHiddenPropertiesHashTable(object, value);
4882 }
4883
4884 Handle<ObjectHashTable> hashtable =
4885 GetOrCreateHiddenPropertiesHashtable(object);
4886
4887 // If it was found, check if the key is already in the dictionary.
4888 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
4889 value);
4890 if (*new_table != *hashtable) {
4891 // If adding the key expanded the dictionary (i.e., Add returned a new
4892 // dictionary), store it back to the object.
4893 SetHiddenPropertiesHashTable(object, new_table);
4894 }
4895
4896 // Return this to mark success.
4897 return object;
4879 } 4898 }
4880 4899
4881 4900
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) { 4901 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
4924 Isolate* isolate = object->GetIsolate(); 4902 Isolate* isolate = object->GetIsolate();
4925 ASSERT(key->IsUniqueName()); 4903 ASSERT(key->IsUniqueName());
4926 4904
4927 if (object->IsJSGlobalProxy()) { 4905 if (object->IsJSGlobalProxy()) {
4928 Handle<Object> proto(object->GetPrototype(), isolate); 4906 Handle<Object> proto(object->GetPrototype(), isolate);
4929 if (proto->IsNull()) return; 4907 if (proto->IsNull()) return;
4930 ASSERT(proto->IsJSGlobalObject()); 4908 ASSERT(proto->IsJSGlobalObject());
4931 return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key); 4909 return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key);
4932 } 4910 }
4933 4911
4934 MaybeObject* hidden_lookup = 4912 Object* inline_value = object->GetHiddenPropertiesHashTable();
4935 object->GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
4936 Object* inline_value = hidden_lookup->ToObjectUnchecked();
4937 4913
4938 // We never delete (inline-stored) identity hashes. 4914 // We never delete (inline-stored) identity hashes.
4939 ASSERT(*key != isolate->heap()->identity_hash_string()); 4915 ASSERT(*key != *isolate->factory()->identity_hash_string());
4940 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; 4916 if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
4941 4917
4942 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); 4918 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
4943 PutIntoObjectHashTable(hashtable, key, isolate->factory()->the_hole_value()); 4919 ObjectHashTable::Put(hashtable, key, isolate->factory()->the_hole_value());
4944 } 4920 }
4945 4921
4946 4922
4947 bool JSObject::HasHiddenProperties() { 4923 bool JSObject::HasHiddenProperties() {
4948 return GetPropertyAttributePostInterceptor(this, 4924 return GetPropertyAttributePostInterceptor(this,
4949 GetHeap()->hidden_string(), 4925 GetHeap()->hidden_string(),
4950 false) != ABSENT; 4926 false) != ABSENT;
4951 } 4927 }
4952 4928
4953 4929
4954 MaybeObject* JSObject::GetHiddenPropertiesHashTable( 4930 Object* JSObject::GetHiddenPropertiesHashTable() {
4955 InitializeHiddenProperties init_option) {
4956 ASSERT(!IsJSGlobalProxy()); 4931 ASSERT(!IsJSGlobalProxy());
4957 Object* inline_value;
4958 if (HasFastProperties()) { 4932 if (HasFastProperties()) {
4959 // If the object has fast properties, check whether the first slot 4933 // If the object has fast properties, check whether the first slot
4960 // in the descriptor array matches the hidden string. Since the 4934 // in the descriptor array matches the hidden string. Since the
4961 // hidden strings hash code is zero (and no other name has hash 4935 // hidden strings hash code is zero (and no other name has hash
4962 // code zero) it will always occupy the first entry if present. 4936 // code zero) it will always occupy the first entry if present.
4963 DescriptorArray* descriptors = this->map()->instance_descriptors(); 4937 DescriptorArray* descriptors = this->map()->instance_descriptors();
4964 if (descriptors->number_of_descriptors() > 0) { 4938 if (descriptors->number_of_descriptors() > 0) {
4965 int sorted_index = descriptors->GetSortedKeyIndex(0); 4939 int sorted_index = descriptors->GetSortedKeyIndex(0);
4966 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && 4940 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
4967 sorted_index < map()->NumberOfOwnDescriptors()) { 4941 sorted_index < map()->NumberOfOwnDescriptors()) {
4968 ASSERT(descriptors->GetType(sorted_index) == FIELD); 4942 ASSERT(descriptors->GetType(sorted_index) == FIELD);
4969 MaybeObject* maybe_value = this->FastPropertyAt( 4943 ASSERT(descriptors->GetDetails(sorted_index).representation().
4970 descriptors->GetDetails(sorted_index).representation(), 4944 IsCompatibleForLoad(Representation::Tagged()));
4945 return this->RawFastPropertyAt(
4971 descriptors->GetFieldIndex(sorted_index)); 4946 descriptors->GetFieldIndex(sorted_index));
4972 if (!maybe_value->To(&inline_value)) return maybe_value;
4973 } else { 4947 } else {
4974 inline_value = GetHeap()->undefined_value(); 4948 return GetHeap()->undefined_value();
4975 } 4949 }
4976 } else { 4950 } else {
4977 inline_value = GetHeap()->undefined_value(); 4951 return GetHeap()->undefined_value();
4978 } 4952 }
4979 } else { 4953 } else {
4980 PropertyAttributes attributes; 4954 PropertyAttributes attributes;
4981 // You can't install a getter on a property indexed by the hidden string, 4955 // 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 4956 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
4983 // object. 4957 // object.
4984 inline_value = 4958 return GetLocalPropertyPostInterceptor(this,
4985 GetLocalPropertyPostInterceptor(this, 4959 GetHeap()->hidden_string(),
4986 GetHeap()->hidden_string(), 4960 &attributes)->ToObjectUnchecked();
4987 &attributes)->ToObjectUnchecked(); 4961 }
4962 }
4963
4964 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
4965 Handle<JSObject> object) {
4966 Isolate* isolate = object->GetIsolate();
4967
4968 static const int kInitialCapacity = 4;
4969 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
4970 if (inline_value->IsHashTable()) {
4971 return Handle<ObjectHashTable>::cast(inline_value);
4988 } 4972 }
4989 4973
4990 if (init_option == ONLY_RETURN_INLINE_VALUE || 4974 Handle<ObjectHashTable> hashtable = isolate->factory()->NewObjectHashTable(
4991 inline_value->IsHashTable()) { 4975 kInitialCapacity,
4992 return inline_value; 4976 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 4977
5003 if (inline_value->IsSmi()) { 4978 if (inline_value->IsSmi()) {
5004 // We were storing the identity hash inline and now allocated an actual 4979 // We were storing the identity hash inline and now allocated an actual
5005 // dictionary. Put the identity hash into the new dictionary. 4980 // dictionary. Put the identity hash into the new dictionary.
5006 MaybeObject* insert_result = 4981 hashtable = ObjectHashTable::Put(hashtable,
5007 hashtable->Put(GetHeap()->identity_hash_string(), inline_value); 4982 isolate->factory()->identity_hash_string(),
5008 ObjectHashTable* new_table; 4983 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 } 4984 }
5013 4985
5014 MaybeObject* store_result = SetLocalPropertyIgnoreAttributesTrampoline( 4986 JSObject::SetLocalPropertyIgnoreAttributes(
5015 GetHeap()->hidden_string(), 4987 object,
4988 isolate->factory()->hidden_string(),
5016 hashtable, 4989 hashtable,
5017 DONT_ENUM, 4990 DONT_ENUM,
5018 OPTIMAL_REPRESENTATION, 4991 OPTIMAL_REPRESENTATION,
5019 ALLOW_AS_CONSTANT, 4992 ALLOW_AS_CONSTANT,
5020 OMIT_EXTENSIBILITY_CHECK); 4993 OMIT_EXTENSIBILITY_CHECK);
5021 if (store_result->IsFailure()) return store_result; 4994
5022 return hashtable; 4995 return hashtable;
5023 } 4996 }
5024 4997
5025 4998
5026 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { 4999 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
5027 ASSERT(!IsJSGlobalProxy()); 5000 Handle<Object> value) {
5001 ASSERT(!object->IsJSGlobalProxy());
5002
5003 Isolate* isolate = object->GetIsolate();
5004
5028 // We can store the identity hash inline iff there is no backing store 5005 // We can store the identity hash inline iff there is no backing store
5029 // for hidden properties yet. 5006 // for hidden properties yet.
5030 ASSERT(HasHiddenProperties() != value->IsSmi()); 5007 ASSERT(object->HasHiddenProperties() != value->IsSmi());
5031 if (HasFastProperties()) { 5008 if (object->HasFastProperties()) {
5032 // If the object has fast properties, check whether the first slot 5009 // If the object has fast properties, check whether the first slot
5033 // in the descriptor array matches the hidden string. Since the 5010 // in the descriptor array matches the hidden string. Since the
5034 // hidden strings hash code is zero (and no other name has hash 5011 // hidden strings hash code is zero (and no other name has hash
5035 // code zero) it will always occupy the first entry if present. 5012 // code zero) it will always occupy the first entry if present.
5036 DescriptorArray* descriptors = this->map()->instance_descriptors(); 5013 DescriptorArray* descriptors = object->map()->instance_descriptors();
5037 if (descriptors->number_of_descriptors() > 0) { 5014 if (descriptors->number_of_descriptors() > 0) {
5038 int sorted_index = descriptors->GetSortedKeyIndex(0); 5015 int sorted_index = descriptors->GetSortedKeyIndex(0);
5039 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && 5016 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string()
5040 sorted_index < map()->NumberOfOwnDescriptors()) { 5017 && sorted_index < object->map()->NumberOfOwnDescriptors()) {
5041 ASSERT(descriptors->GetType(sorted_index) == FIELD); 5018 ASSERT(descriptors->GetType(sorted_index) == FIELD);
5042 FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value); 5019 object->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
5043 return this; 5020 *value);
5021 return object;
5044 } 5022 }
5045 } 5023 }
5046 } 5024 }
5047 MaybeObject* store_result = SetLocalPropertyIgnoreAttributesTrampoline( 5025
5048 GetHeap()->hidden_string(), 5026 SetLocalPropertyIgnoreAttributes(object,
5049 value, 5027 isolate->factory()->hidden_string(),
5050 DONT_ENUM, 5028 value,
5051 OPTIMAL_REPRESENTATION, 5029 DONT_ENUM,
5052 ALLOW_AS_CONSTANT, 5030 OPTIMAL_REPRESENTATION,
5053 OMIT_EXTENSIBILITY_CHECK); 5031 ALLOW_AS_CONSTANT,
5054 if (store_result->IsFailure()) return store_result; 5032 OMIT_EXTENSIBILITY_CHECK);
5055 return this; 5033 return object;
5056 } 5034 }
5057 5035
5058 5036
5059 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, 5037 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
5060 Handle<Name> name, 5038 Handle<Name> name,
5061 DeleteMode mode) { 5039 DeleteMode mode) {
5062 // Check local property, ignore interceptor. 5040 // Check local property, ignore interceptor.
5063 Isolate* isolate = object->GetIsolate(); 5041 Isolate* isolate = object->GetIsolate();
5064 LookupResult result(isolate); 5042 LookupResult result(isolate);
5065 object->LocalLookupRealNamedProperty(*name, &result); 5043 object->LocalLookupRealNamedProperty(*name, &result);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
5198 // Skip interceptor if forcing deletion. 5176 // Skip interceptor if forcing deletion.
5199 Handle<Object> result; 5177 Handle<Object> result;
5200 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { 5178 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
5201 result = DeleteElementWithInterceptor(object, index); 5179 result = DeleteElementWithInterceptor(object, index);
5202 } else { 5180 } else {
5203 result = AccessorDelete(object, index, mode); 5181 result = AccessorDelete(object, index, mode);
5204 } 5182 }
5205 5183
5206 if (should_enqueue_change_record && !HasLocalElement(object, index)) { 5184 if (should_enqueue_change_record && !HasLocalElement(object, index)) {
5207 Handle<String> name = factory->Uint32ToString(index); 5185 Handle<String> name = factory->Uint32ToString(index);
5208 EnqueueChangeRecord(object, "deleted", name, old_value); 5186 EnqueueChangeRecord(object, "delete", name, old_value);
5209 } 5187 }
5210 5188
5211 return result; 5189 return result;
5212 } 5190 }
5213 5191
5214 5192
5215 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, 5193 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
5216 Handle<Name> name, 5194 Handle<Name> name,
5217 DeleteMode mode) { 5195 DeleteMode mode) {
5218 Isolate* isolate = object->GetIsolate(); 5196 Isolate* isolate = object->GetIsolate();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
5274 result = DeletePropertyWithInterceptor(object, name); 5252 result = DeletePropertyWithInterceptor(object, name);
5275 } 5253 }
5276 } else { 5254 } else {
5277 // Normalize object if needed. 5255 // Normalize object if needed.
5278 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 5256 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
5279 // Make sure the properties are normalized before removing the entry. 5257 // Make sure the properties are normalized before removing the entry.
5280 result = DeleteNormalizedProperty(object, name, mode); 5258 result = DeleteNormalizedProperty(object, name, mode);
5281 } 5259 }
5282 5260
5283 if (is_observed && !HasLocalProperty(object, name)) { 5261 if (is_observed && !HasLocalProperty(object, name)) {
5284 EnqueueChangeRecord(object, "deleted", name, old_value); 5262 EnqueueChangeRecord(object, "delete", name, old_value);
5285 } 5263 }
5286 5264
5287 return result; 5265 return result;
5288 } 5266 }
5289 5267
5290 5268
5291 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, 5269 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
5292 uint32_t index, 5270 uint32_t index,
5293 DeleteMode mode) { 5271 DeleteMode mode) {
5294 if (object->IsJSProxy()) { 5272 if (object->IsJSProxy()) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
5436 } 5414 }
5437 } 5415 }
5438 5416
5439 // No references to object. 5417 // No references to object.
5440 return false; 5418 return false;
5441 } 5419 }
5442 5420
5443 5421
5444 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { 5422 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
5445 Isolate* isolate = object->GetIsolate(); 5423 Isolate* isolate = object->GetIsolate();
5424
5425 if (!object->map()->is_extensible()) return object;
5426
5446 if (object->IsAccessCheckNeeded() && 5427 if (object->IsAccessCheckNeeded() &&
5447 !isolate->MayNamedAccess(*object, 5428 !isolate->MayNamedAccess(*object,
5448 isolate->heap()->undefined_value(), 5429 isolate->heap()->undefined_value(),
5449 v8::ACCESS_KEYS)) { 5430 v8::ACCESS_KEYS)) {
5450 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); 5431 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5451 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); 5432 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
5452 return isolate->factory()->false_value(); 5433 return isolate->factory()->false_value();
5453 } 5434 }
5454 5435
5455 if (object->IsJSGlobalProxy()) { 5436 if (object->IsJSGlobalProxy()) {
(...skipping 22 matching lines...) Expand all
5478 dictionary->set_requires_slow_elements(); 5459 dictionary->set_requires_slow_elements();
5479 5460
5480 // Do a map transition, other objects with this map may still 5461 // Do a map transition, other objects with this map may still
5481 // be extensible. 5462 // be extensible.
5482 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. 5463 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
5483 Handle<Map> new_map = Map::Copy(handle(object->map())); 5464 Handle<Map> new_map = Map::Copy(handle(object->map()));
5484 5465
5485 new_map->set_is_extensible(false); 5466 new_map->set_is_extensible(false);
5486 object->set_map(*new_map); 5467 object->set_map(*new_map);
5487 ASSERT(!object->map()->is_extensible()); 5468 ASSERT(!object->map()->is_extensible());
5469
5470 if (FLAG_harmony_observation && object->map()->is_observed()) {
5471 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
5472 isolate->factory()->the_hole_value());
5473 }
5488 return object; 5474 return object;
5489 } 5475 }
5490 5476
5491 5477
5492 template<typename Dictionary> 5478 template<typename Dictionary>
5493 static void FreezeDictionary(Dictionary* dictionary) { 5479 static void FreezeDictionary(Dictionary* dictionary) {
5494 int capacity = dictionary->Capacity(); 5480 int capacity = dictionary->Capacity();
5495 for (int i = 0; i < capacity; i++) { 5481 for (int i = 0; i < capacity; i++) {
5496 Object* k = dictionary->KeyAt(i); 5482 Object* k = dictionary->KeyAt(i);
5497 if (dictionary->IsKey(k)) { 5483 if (dictionary->IsKey(k)) {
5498 PropertyDetails details = dictionary->DetailsAt(i); 5484 PropertyDetails details = dictionary->DetailsAt(i);
5499 int attrs = DONT_DELETE; 5485 int attrs = DONT_DELETE;
5500 // READ_ONLY is an invalid attribute for JS setters/getters. 5486 // READ_ONLY is an invalid attribute for JS setters/getters.
5501 if (details.type() != CALLBACKS || 5487 if (details.type() != CALLBACKS ||
5502 !dictionary->ValueAt(i)->IsAccessorPair()) { 5488 !dictionary->ValueAt(i)->IsAccessorPair()) {
5503 attrs |= READ_ONLY; 5489 attrs |= READ_ONLY;
5504 } 5490 }
5505 details = details.CopyAddAttributes( 5491 details = details.CopyAddAttributes(
5506 static_cast<PropertyAttributes>(attrs)); 5492 static_cast<PropertyAttributes>(attrs));
5507 dictionary->DetailsAtPut(i, details); 5493 dictionary->DetailsAtPut(i, details);
5508 } 5494 }
5509 } 5495 }
5510 } 5496 }
5511 5497
5512 5498
5513 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { 5499 Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
5514 // Freezing non-strict arguments should be handled elsewhere. 5500 // Freezing non-strict arguments should be handled elsewhere.
5515 ASSERT(!object->HasNonStrictArgumentsElements()); 5501 ASSERT(!object->HasNonStrictArgumentsElements());
5502 ASSERT(!object->map()->is_observed());
5516 5503
5517 if (object->map()->is_frozen()) return object; 5504 if (object->map()->is_frozen()) return object;
5518 5505
5519 Isolate* isolate = object->GetIsolate(); 5506 Isolate* isolate = object->GetIsolate();
5520 if (object->IsAccessCheckNeeded() && 5507 if (object->IsAccessCheckNeeded() &&
5521 !isolate->MayNamedAccess(*object, 5508 !isolate->MayNamedAccess(*object,
5522 isolate->heap()->undefined_value(), 5509 isolate->heap()->undefined_value(),
5523 v8::ACCESS_KEYS)) { 5510 v8::ACCESS_KEYS)) {
5524 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); 5511 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5525 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); 5512 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
5830 // Deep copy local elements. 5817 // Deep copy local elements.
5831 // Pixel elements cannot be created using an object literal. 5818 // Pixel elements cannot be created using an object literal.
5832 ASSERT(!copy->HasExternalArrayElements()); 5819 ASSERT(!copy->HasExternalArrayElements());
5833 switch (copy->GetElementsKind()) { 5820 switch (copy->GetElementsKind()) {
5834 case FAST_SMI_ELEMENTS: 5821 case FAST_SMI_ELEMENTS:
5835 case FAST_ELEMENTS: 5822 case FAST_ELEMENTS:
5836 case FAST_HOLEY_SMI_ELEMENTS: 5823 case FAST_HOLEY_SMI_ELEMENTS:
5837 case FAST_HOLEY_ELEMENTS: { 5824 case FAST_HOLEY_ELEMENTS: {
5838 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); 5825 Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
5839 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { 5826 if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
5840 isolate->counters()->cow_arrays_created_runtime()->Increment(); 5827 if (copying) {
5828 isolate->counters()->cow_arrays_created_runtime()->Increment();
5829 }
5841 #ifdef DEBUG 5830 #ifdef DEBUG
5842 for (int i = 0; i < elements->length(); i++) { 5831 for (int i = 0; i < elements->length(); i++) {
5843 ASSERT(!elements->get(i)->IsJSObject()); 5832 ASSERT(!elements->get(i)->IsJSObject());
5844 } 5833 }
5845 #endif 5834 #endif
5846 } else { 5835 } else {
5847 for (int i = 0; i < elements->length(); i++) { 5836 for (int i = 0; i < elements->length(); i++) {
5848 Handle<Object> value(elements->get(i), isolate); 5837 Handle<Object> value(elements->get(i), isolate);
5849 ASSERT(value->IsSmi() || 5838 ASSERT(value->IsSmi() ||
5850 value->IsTheHole() || 5839 value->IsTheHole() ||
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
6223 return !AccessorInfo::cast(obj)->prohibits_overwriting(); 6212 return !AccessorInfo::cast(obj)->prohibits_overwriting();
6224 } 6213 }
6225 if (obj->IsAccessorPair()) { 6214 if (obj->IsAccessorPair()) {
6226 return !AccessorPair::cast(obj)->prohibits_overwriting(); 6215 return !AccessorPair::cast(obj)->prohibits_overwriting();
6227 } 6216 }
6228 } 6217 }
6229 return true; 6218 return true;
6230 } 6219 }
6231 6220
6232 6221
6222 bool Map::DictionaryElementsInPrototypeChainOnly() {
6223 Heap* heap = GetHeap();
6224
6225 if (IsDictionaryElementsKind(elements_kind())) {
6226 return false;
6227 }
6228
6229 for (Object* prototype = this->prototype();
6230 prototype != heap->null_value();
6231 prototype = prototype->GetPrototype(GetIsolate())) {
6232 if (prototype->IsJSProxy()) {
6233 // Be conservative, don't walk into proxies.
6234 return true;
6235 }
6236
6237 if (IsDictionaryElementsKind(
6238 JSObject::cast(prototype)->map()->elements_kind())) {
6239 return true;
6240 }
6241 }
6242
6243 return false;
6244 }
6245
6246
6233 void JSObject::SetElementCallback(Handle<JSObject> object, 6247 void JSObject::SetElementCallback(Handle<JSObject> object,
6234 uint32_t index, 6248 uint32_t index,
6235 Handle<Object> structure, 6249 Handle<Object> structure,
6236 PropertyAttributes attributes) { 6250 PropertyAttributes attributes) {
6237 Heap* heap = object->GetHeap(); 6251 Heap* heap = object->GetHeap();
6238 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); 6252 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6239 6253
6240 // Normalize elements to make this operation simple. 6254 // Normalize elements to make this operation simple.
6255 bool had_dictionary_elements = object->HasDictionaryElements();
6241 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); 6256 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
6242 ASSERT(object->HasDictionaryElements() || 6257 ASSERT(object->HasDictionaryElements() ||
6243 object->HasDictionaryArgumentsElements()); 6258 object->HasDictionaryArgumentsElements());
6244 6259
6245 // Update the dictionary with the new CALLBACKS property. 6260 // Update the dictionary with the new CALLBACKS property.
6246 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, 6261 dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6247 details); 6262 details);
6248 dictionary->set_requires_slow_elements(); 6263 dictionary->set_requires_slow_elements();
6249 6264
6250 // Update the dictionary backing store on the object. 6265 // Update the dictionary backing store on the object.
6251 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { 6266 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) {
6252 // Also delete any parameter alias. 6267 // Also delete any parameter alias.
6253 // 6268 //
6254 // TODO(kmillikin): when deleting the last parameter alias we could 6269 // TODO(kmillikin): when deleting the last parameter alias we could
6255 // switch to a direct backing store without the parameter map. This 6270 // switch to a direct backing store without the parameter map. This
6256 // would allow GC of the context. 6271 // would allow GC of the context.
6257 FixedArray* parameter_map = FixedArray::cast(object->elements()); 6272 FixedArray* parameter_map = FixedArray::cast(object->elements());
6258 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { 6273 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6259 parameter_map->set(index + 2, heap->the_hole_value()); 6274 parameter_map->set(index + 2, heap->the_hole_value());
6260 } 6275 }
6261 parameter_map->set(1, *dictionary); 6276 parameter_map->set(1, *dictionary);
6262 } else { 6277 } else {
6263 object->set_elements(*dictionary); 6278 object->set_elements(*dictionary);
6279
6280 if (!had_dictionary_elements) {
6281 // KeyedStoreICs (at least the non-generic ones) need a reset.
6282 heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6283 }
6264 } 6284 }
6265 } 6285 }
6266 6286
6267 6287
6268 void JSObject::SetPropertyCallback(Handle<JSObject> object, 6288 void JSObject::SetPropertyCallback(Handle<JSObject> object,
6269 Handle<Name> name, 6289 Handle<Name> name,
6270 Handle<Object> structure, 6290 Handle<Object> structure,
6271 PropertyAttributes attributes) { 6291 PropertyAttributes attributes) {
6272 // Normalize object to make this operation simple. 6292 // Normalize object to make this operation simple.
6273 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); 6293 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
6353 6373
6354 if (is_element) { 6374 if (is_element) {
6355 DefineElementAccessor( 6375 DefineElementAccessor(
6356 object, index, getter, setter, attributes, access_control); 6376 object, index, getter, setter, attributes, access_control);
6357 } else { 6377 } else {
6358 DefinePropertyAccessor( 6378 DefinePropertyAccessor(
6359 object, name, getter, setter, attributes, access_control); 6379 object, name, getter, setter, attributes, access_control);
6360 } 6380 }
6361 6381
6362 if (is_observed) { 6382 if (is_observed) {
6363 const char* type = preexists ? "reconfigured" : "new"; 6383 const char* type = preexists ? "reconfigure" : "add";
6364 EnqueueChangeRecord(object, type, name, old_value); 6384 EnqueueChangeRecord(object, type, name, old_value);
6365 } 6385 }
6366 } 6386 }
6367 6387
6368 6388
6369 static bool TryAccessorTransition(JSObject* self, 6389 static bool TryAccessorTransition(JSObject* self,
6370 Map* transitioned_map, 6390 Map* transitioned_map,
6371 int target_descriptor, 6391 int target_descriptor,
6372 AccessorComponent component, 6392 AccessorComponent component,
6373 Object* accessor, 6393 Object* accessor,
(...skipping 3503 matching lines...) Expand 10 before | Expand all | Expand 10 after
9877 9897
9878 ASSERT(map() == (shared()->is_classic_mode() 9898 ASSERT(map() == (shared()->is_classic_mode()
9879 ? native_context->function_map() 9899 ? native_context->function_map()
9880 : native_context->strict_mode_function_map())); 9900 : native_context->strict_mode_function_map()));
9881 9901
9882 set_map(no_prototype_map); 9902 set_map(no_prototype_map);
9883 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); 9903 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
9884 } 9904 }
9885 9905
9886 9906
9907 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
9908 if (function->has_initial_map()) return;
9909 Isolate* isolate = function->GetIsolate();
9910
9911 // First create a new map with the size and number of in-object properties
9912 // suggested by the function.
9913 InstanceType instance_type;
9914 int instance_size;
9915 int in_object_properties;
9916 if (function->shared()->is_generator()) {
9917 instance_type = JS_GENERATOR_OBJECT_TYPE;
9918 instance_size = JSGeneratorObject::kSize;
9919 in_object_properties = 0;
9920 } else {
9921 instance_type = JS_OBJECT_TYPE;
9922 instance_size = function->shared()->CalculateInstanceSize();
9923 in_object_properties = function->shared()->CalculateInObjectProperties();
9924 }
9925 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
9926
9927 // Fetch or allocate prototype.
9928 Handle<Object> prototype;
9929 if (function->has_instance_prototype()) {
9930 prototype = handle(function->instance_prototype(), isolate);
9931 } else {
9932 prototype = isolate->factory()->NewFunctionPrototype(function);
9933 }
9934 map->set_inobject_properties(in_object_properties);
9935 map->set_unused_property_fields(in_object_properties);
9936 map->set_prototype(*prototype);
9937 ASSERT(map->has_fast_object_elements());
9938
9939 if (!function->shared()->is_generator()) {
9940 function->shared()->StartInobjectSlackTracking(*map);
9941 }
9942
9943 // Finally link initial map and constructor function.
9944 function->set_initial_map(*map);
9945 map->set_constructor(*function);
9946 }
9947
9948
9887 void JSFunction::SetInstanceClassName(String* name) { 9949 void JSFunction::SetInstanceClassName(String* name) {
9888 shared()->set_instance_class_name(name); 9950 shared()->set_instance_class_name(name);
9889 } 9951 }
9890 9952
9891 9953
9892 void JSFunction::PrintName(FILE* out) { 9954 void JSFunction::PrintName(FILE* out) {
9893 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); 9955 SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
9894 PrintF(out, "%s", *name); 9956 PrintF(out, "%s", *name);
9895 } 9957 }
9896 9958
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
10310 rinfo->IsPatchedDebugBreakSlotSequence())); 10372 rinfo->IsPatchedDebugBreakSlotSequence()));
10311 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); 10373 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
10312 Object* old_target = target; 10374 Object* old_target = target;
10313 VisitPointer(&target); 10375 VisitPointer(&target);
10314 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. 10376 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
10315 } 10377 }
10316 10378
10317 10379
10318 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { 10380 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
10319 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); 10381 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
10320 VisitPointer(rinfo->target_object_address()); 10382 Object* p = rinfo->target_object();
10383 VisitPointer(&p);
10321 } 10384 }
10322 10385
10323 10386
10324 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { 10387 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
10325 Address* p = rinfo->target_reference_address(); 10388 Address p = rinfo->target_reference();
10326 VisitExternalReference(p); 10389 VisitExternalReference(&p);
10327 } 10390 }
10328 10391
10329 10392
10330 void Code::InvalidateRelocation() { 10393 void Code::InvalidateRelocation() {
10331 set_relocation_info(GetHeap()->empty_byte_array()); 10394 set_relocation_info(GetHeap()->empty_byte_array());
10332 } 10395 }
10333 10396
10334 10397
10335 void Code::Relocate(intptr_t delta) { 10398 void Code::Relocate(intptr_t delta) {
10336 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { 10399 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
10570 if (--n == 0) { 10633 if (--n == 0) {
10571 info->set_target_cell(replace_with); 10634 info->set_target_cell(replace_with);
10572 return; 10635 return;
10573 } 10636 }
10574 } 10637 }
10575 UNREACHABLE(); 10638 UNREACHABLE();
10576 } 10639 }
10577 10640
10578 10641
10579 void Code::ClearInlineCaches() { 10642 void Code::ClearInlineCaches() {
10643 ClearInlineCaches(NULL);
10644 }
10645
10646
10647 void Code::ClearInlineCaches(Code::Kind kind) {
10648 ClearInlineCaches(&kind);
10649 }
10650
10651
10652 void Code::ClearInlineCaches(Code::Kind* kind) {
10580 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | 10653 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10581 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | 10654 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10582 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | 10655 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
10583 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); 10656 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
10584 for (RelocIterator it(this, mask); !it.done(); it.next()) { 10657 for (RelocIterator it(this, mask); !it.done(); it.next()) {
10585 RelocInfo* info = it.rinfo(); 10658 RelocInfo* info = it.rinfo();
10586 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); 10659 Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10587 if (target->is_inline_cache_stub()) { 10660 if (target->is_inline_cache_stub()) {
10588 IC::Clear(this->GetIsolate(), info->pc()); 10661 if (kind == NULL || *kind == target->kind()) {
10662 IC::Clear(this->GetIsolate(), info->pc());
10663 }
10589 } 10664 }
10590 } 10665 }
10591 } 10666 }
10592 10667
10593 10668
10594 void Code::ClearTypeFeedbackCells(Heap* heap) { 10669 void Code::ClearTypeFeedbackCells(Heap* heap) {
10595 if (kind() != FUNCTION) return; 10670 if (kind() != FUNCTION) return;
10596 Object* raw_info = type_feedback_info(); 10671 Object* raw_info = type_feedback_info();
10597 if (raw_info->IsTypeFeedbackInfo()) { 10672 if (raw_info->IsTypeFeedbackInfo()) {
10598 TypeFeedbackCells* type_feedback_cells = 10673 TypeFeedbackCells* type_feedback_cells =
(...skipping 25 matching lines...) Expand all
10624 PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY); 10699 PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
10625 } 10700 }
10626 10701
10627 10702
10628 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) { 10703 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
10629 PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge, 10704 PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
10630 NO_MARKING_PARITY); 10705 NO_MARKING_PARITY);
10631 } 10706 }
10632 10707
10633 10708
10709 static Code::Age EffectiveAge(Code::Age age) {
10710 if (age == Code::kNotExecutedCodeAge) {
10711 // Treat that's never been executed as old immediately.
10712 age = Code::kIsOldCodeAge;
10713 } else if (age == Code::kExecutedOnceCodeAge) {
10714 // Pre-age code that has only been executed once.
10715 age = Code::kPreAgedCodeAge;
10716 }
10717 return age;
10718 }
10719
10720
10634 void Code::MakeOlder(MarkingParity current_parity) { 10721 void Code::MakeOlder(MarkingParity current_parity) {
10635 byte* sequence = FindCodeAgeSequence(); 10722 byte* sequence = FindCodeAgeSequence();
10636 if (sequence != NULL) { 10723 if (sequence != NULL) {
10637 Age age; 10724 Age age;
10638 MarkingParity code_parity; 10725 MarkingParity code_parity;
10639 GetCodeAgeAndParity(sequence, &age, &code_parity); 10726 GetCodeAgeAndParity(sequence, &age, &code_parity);
10727 age = EffectiveAge(age);
10640 if (age != kLastCodeAge && code_parity != current_parity) { 10728 if (age != kLastCodeAge && code_parity != current_parity) {
10641 PatchPlatformCodeAge(GetIsolate(), 10729 PatchPlatformCodeAge(GetIsolate(),
10642 sequence, 10730 sequence,
10643 static_cast<Age>(age + 1), 10731 static_cast<Age>(age + 1),
10644 current_parity); 10732 current_parity);
10645 } 10733 }
10646 } 10734 }
10647 } 10735 }
10648 10736
10649 10737
10650 bool Code::IsOld() { 10738 bool Code::IsOld() {
10651 Age age = GetAge(); 10739 return GetAge() >= kIsOldCodeAge;
10652 return age >= kIsOldCodeAge;
10653 } 10740 }
10654 10741
10655 10742
10656 byte* Code::FindCodeAgeSequence() { 10743 byte* Code::FindCodeAgeSequence() {
10657 return FLAG_age_code && 10744 return FLAG_age_code &&
10658 prologue_offset() != Code::kPrologueOffsetNotSet && 10745 prologue_offset() != Code::kPrologueOffsetNotSet &&
10659 (kind() == OPTIMIZED_FUNCTION || 10746 (kind() == OPTIMIZED_FUNCTION ||
10660 (kind() == FUNCTION && !has_debug_break_slots())) 10747 (kind() == FUNCTION && !has_debug_break_slots()))
10661 ? instruction_start() + prologue_offset() 10748 ? instruction_start() + prologue_offset()
10662 : NULL; 10749 : NULL;
10663 } 10750 }
10664 10751
10665 10752
10666 Code::Age Code::GetAge() { 10753 Code::Age Code::GetAge() {
10754 return EffectiveAge(GetRawAge());
10755 }
10756
10757
10758 Code::Age Code::GetRawAge() {
10667 byte* sequence = FindCodeAgeSequence(); 10759 byte* sequence = FindCodeAgeSequence();
10668 if (sequence == NULL) { 10760 if (sequence == NULL) {
10669 return Code::kNoAgeCodeAge; 10761 return kNoAgeCodeAge;
10670 } 10762 }
10671 Age age; 10763 Age age;
10672 MarkingParity parity; 10764 MarkingParity parity;
10673 GetCodeAgeAndParity(sequence, &age, &parity); 10765 GetCodeAgeAndParity(sequence, &age, &parity);
10674 return age; 10766 return age;
10675 } 10767 }
10676 10768
10677 10769
10678 void Code::GetCodeAgeAndParity(Code* code, Age* age, 10770 void Code::GetCodeAgeAndParity(Code* code, Age* age,
10679 MarkingParity* parity) { 10771 MarkingParity* parity) {
(...skipping 10 matching lines...) Expand all
10690 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ 10782 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \
10691 if (code == stub) { \ 10783 if (code == stub) { \
10692 *age = k##AGE##CodeAge; \ 10784 *age = k##AGE##CodeAge; \
10693 *parity = ODD_MARKING_PARITY; \ 10785 *parity = ODD_MARKING_PARITY; \
10694 return; \ 10786 return; \
10695 } 10787 }
10696 CODE_AGE_LIST(HANDLE_CODE_AGE) 10788 CODE_AGE_LIST(HANDLE_CODE_AGE)
10697 #undef HANDLE_CODE_AGE 10789 #undef HANDLE_CODE_AGE
10698 stub = *builtins->MarkCodeAsExecutedOnce(); 10790 stub = *builtins->MarkCodeAsExecutedOnce();
10699 if (code == stub) { 10791 if (code == stub) {
10700 // Treat that's never been executed as old immediatly. 10792 *age = kNotExecutedCodeAge;
10701 *age = kIsOldCodeAge;
10702 *parity = NO_MARKING_PARITY; 10793 *parity = NO_MARKING_PARITY;
10703 return; 10794 return;
10704 } 10795 }
10705 stub = *builtins->MarkCodeAsExecutedTwice(); 10796 stub = *builtins->MarkCodeAsExecutedTwice();
10706 if (code == stub) { 10797 if (code == stub) {
10707 // Pre-age code that has only been executed once. 10798 *age = kExecutedOnceCodeAge;
10708 *age = kPreAgedCodeAge;
10709 *parity = NO_MARKING_PARITY; 10799 *parity = NO_MARKING_PARITY;
10710 return; 10800 return;
10711 } 10801 }
10712 UNREACHABLE(); 10802 UNREACHABLE();
10713 } 10803 }
10714 10804
10715 10805
10716 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { 10806 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
10717 Builtins* builtins = isolate->builtins(); 10807 Builtins* builtins = isolate->builtins();
10718 switch (age) { 10808 switch (age) {
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
11399 Handle<Object> hresult; 11489 Handle<Object> hresult;
11400 if (!result->ToHandle(&hresult, isolate)) return result; 11490 if (!result->ToHandle(&hresult, isolate)) return result;
11401 11491
11402 CHECK(self->length()->ToArrayIndex(&new_length)); 11492 CHECK(self->length()->ToArrayIndex(&new_length));
11403 if (old_length == new_length) return *hresult; 11493 if (old_length == new_length) return *hresult;
11404 11494
11405 BeginPerformSplice(self); 11495 BeginPerformSplice(self);
11406 11496
11407 for (int i = 0; i < indices.length(); ++i) { 11497 for (int i = 0; i < indices.length(); ++i) {
11408 JSObject::EnqueueChangeRecord( 11498 JSObject::EnqueueChangeRecord(
11409 self, "deleted", isolate->factory()->Uint32ToString(indices[i]), 11499 self, "delete", isolate->factory()->Uint32ToString(indices[i]),
11410 old_values[i]); 11500 old_values[i]);
11411 } 11501 }
11412 JSObject::EnqueueChangeRecord( 11502 JSObject::EnqueueChangeRecord(
11413 self, "updated", isolate->factory()->length_string(), 11503 self, "update", isolate->factory()->length_string(),
11414 old_length_handle); 11504 old_length_handle);
11415 11505
11416 EndPerformSplice(self); 11506 EndPerformSplice(self);
11417 11507
11418 uint32_t index = Min(old_length, new_length); 11508 uint32_t index = Min(old_length, new_length);
11419 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; 11509 uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
11420 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; 11510 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
11421 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); 11511 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
11422 if (delete_count > 0) { 11512 if (delete_count > 0) {
11423 for (int i = indices.length() - 1; i >= 0; i--) { 11513 for (int i = indices.length() - 1; i >= 0; i--) {
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
11751 pt = pt->GetPrototype(isolate)) { 11841 pt = pt->GetPrototype(isolate)) {
11752 if (JSReceiver::cast(pt) == *object) { 11842 if (JSReceiver::cast(pt) == *object) {
11753 // Cycle detected. 11843 // Cycle detected.
11754 Handle<Object> error = isolate->factory()->NewError( 11844 Handle<Object> error = isolate->factory()->NewError(
11755 "cyclic_proto", HandleVector<Object>(NULL, 0)); 11845 "cyclic_proto", HandleVector<Object>(NULL, 0));
11756 isolate->Throw(*error); 11846 isolate->Throw(*error);
11757 return Handle<Object>(); 11847 return Handle<Object>();
11758 } 11848 }
11759 } 11849 }
11760 11850
11851 bool dictionary_elements_in_chain =
11852 object->map()->DictionaryElementsInPrototypeChainOnly();
11761 Handle<JSObject> real_receiver = object; 11853 Handle<JSObject> real_receiver = object;
11762 11854
11763 if (skip_hidden_prototypes) { 11855 if (skip_hidden_prototypes) {
11764 // Find the first object in the chain whose prototype object is not 11856 // Find the first object in the chain whose prototype object is not
11765 // hidden and set the new prototype on that object. 11857 // hidden and set the new prototype on that object.
11766 Object* current_proto = real_receiver->GetPrototype(); 11858 Object* current_proto = real_receiver->GetPrototype();
11767 while (current_proto->IsJSObject() && 11859 while (current_proto->IsJSObject() &&
11768 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 11860 JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
11769 real_receiver = handle(JSObject::cast(current_proto), isolate); 11861 real_receiver = handle(JSObject::cast(current_proto), isolate);
11770 current_proto = current_proto->GetPrototype(isolate); 11862 current_proto = current_proto->GetPrototype(isolate);
(...skipping 12 matching lines...) Expand all
11783 11875
11784 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); 11876 Handle<Map> new_map = Map::GetPrototypeTransition(map, value);
11785 if (new_map.is_null()) { 11877 if (new_map.is_null()) {
11786 new_map = Map::Copy(map); 11878 new_map = Map::Copy(map);
11787 Map::PutPrototypeTransition(map, value, new_map); 11879 Map::PutPrototypeTransition(map, value, new_map);
11788 new_map->set_prototype(*value); 11880 new_map->set_prototype(*value);
11789 } 11881 }
11790 ASSERT(new_map->prototype() == *value); 11882 ASSERT(new_map->prototype() == *value);
11791 real_receiver->set_map(*new_map); 11883 real_receiver->set_map(*new_map);
11792 11884
11885 if (!dictionary_elements_in_chain &&
11886 new_map->DictionaryElementsInPrototypeChainOnly()) {
11887 // If the prototype chain didn't previously have element callbacks, then
11888 // KeyedStoreICs need to be cleared to ensure any that involve this
11889 // map go generic.
11890 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11891 }
11892
11793 heap->ClearInstanceofCache(); 11893 heap->ClearInstanceofCache();
11794 ASSERT(size == object->Size()); 11894 ASSERT(size == object->Size());
11795 return value; 11895 return value;
11796 } 11896 }
11797 11897
11798 11898
11799 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, 11899 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
11800 uint32_t first_arg, 11900 uint32_t first_arg,
11801 uint32_t arg_count, 11901 uint32_t arg_count,
11802 EnsureElementsMode mode) { 11902 EnsureElementsMode mode) {
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after
12549 if (self->IsJSArray() && 12649 if (self->IsJSArray() &&
12550 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { 12650 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) {
12551 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), 12651 new_length_handle = handle(Handle<JSArray>::cast(self)->length(),
12552 isolate); 12652 isolate);
12553 uint32_t old_length = 0; 12653 uint32_t old_length = 0;
12554 uint32_t new_length = 0; 12654 uint32_t new_length = 0;
12555 CHECK(old_length_handle->ToArrayIndex(&old_length)); 12655 CHECK(old_length_handle->ToArrayIndex(&old_length));
12556 CHECK(new_length_handle->ToArrayIndex(&new_length)); 12656 CHECK(new_length_handle->ToArrayIndex(&new_length));
12557 12657
12558 BeginPerformSplice(Handle<JSArray>::cast(self)); 12658 BeginPerformSplice(Handle<JSArray>::cast(self));
12559 EnqueueChangeRecord(self, "new", name, old_value); 12659 EnqueueChangeRecord(self, "add", name, old_value);
12560 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(), 12660 EnqueueChangeRecord(self, "update", isolate->factory()->length_string(),
12561 old_length_handle); 12661 old_length_handle);
12562 EndPerformSplice(Handle<JSArray>::cast(self)); 12662 EndPerformSplice(Handle<JSArray>::cast(self));
12563 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); 12663 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
12564 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, 12664 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted,
12565 new_length - old_length); 12665 new_length - old_length);
12566 } else { 12666 } else {
12567 EnqueueChangeRecord(self, "new", name, old_value); 12667 EnqueueChangeRecord(self, "add", name, old_value);
12568 } 12668 }
12569 } else if (old_value->IsTheHole()) { 12669 } else if (old_value->IsTheHole()) {
12570 EnqueueChangeRecord(self, "reconfigured", name, old_value); 12670 EnqueueChangeRecord(self, "reconfigure", name, old_value);
12571 } else { 12671 } else {
12572 Handle<Object> new_value = Object::GetElement(isolate, self, index); 12672 Handle<Object> new_value = Object::GetElement(isolate, self, index);
12573 bool value_changed = !old_value->SameValue(*new_value); 12673 bool value_changed = !old_value->SameValue(*new_value);
12574 if (old_attributes != new_attributes) { 12674 if (old_attributes != new_attributes) {
12575 if (!value_changed) old_value = isolate->factory()->the_hole_value(); 12675 if (!value_changed) old_value = isolate->factory()->the_hole_value();
12576 EnqueueChangeRecord(self, "reconfigured", name, old_value); 12676 EnqueueChangeRecord(self, "reconfigure", name, old_value);
12577 } else if (value_changed) { 12677 } else if (value_changed) {
12578 EnqueueChangeRecord(self, "updated", name, old_value); 12678 EnqueueChangeRecord(self, "update", name, old_value);
12579 } 12679 }
12580 } 12680 }
12581 12681
12582 return *hresult; 12682 return *hresult;
12583 } 12683 }
12584 12684
12585 12685
12586 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 12686 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
12587 Object* value, 12687 Object* value,
12588 PropertyAttributes attr, 12688 PropertyAttributes attr,
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
12771 12871
12772 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 12872 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
12773 ASSERT(!map()->is_observed()); 12873 ASSERT(!map()->is_observed());
12774 ElementsKind from_kind = map()->elements_kind(); 12874 ElementsKind from_kind = map()->elements_kind();
12775 12875
12776 if (IsFastHoleyElementsKind(from_kind)) { 12876 if (IsFastHoleyElementsKind(from_kind)) {
12777 to_kind = GetHoleyElementsKind(to_kind); 12877 to_kind = GetHoleyElementsKind(to_kind);
12778 } 12878 }
12779 12879
12780 if (from_kind == to_kind) return this; 12880 if (from_kind == to_kind) return this;
12781 12881 // Don't update the site if to_kind isn't fast
12782 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); 12882 if (IsFastElementsKind(to_kind)) {
12783 if (maybe_failure->IsFailure()) return maybe_failure; 12883 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
12884 if (maybe_failure->IsFailure()) return maybe_failure;
12885 }
12784 12886
12785 Isolate* isolate = GetIsolate(); 12887 Isolate* isolate = GetIsolate();
12786 if (elements() == isolate->heap()->empty_fixed_array() || 12888 if (elements() == isolate->heap()->empty_fixed_array() ||
12787 (IsFastSmiOrObjectElementsKind(from_kind) && 12889 (IsFastSmiOrObjectElementsKind(from_kind) &&
12788 IsFastSmiOrObjectElementsKind(to_kind)) || 12890 IsFastSmiOrObjectElementsKind(to_kind)) ||
12789 (from_kind == FAST_DOUBLE_ELEMENTS && 12891 (from_kind == FAST_DOUBLE_ELEMENTS &&
12790 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { 12892 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12791 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); 12893 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12792 // No change is needed to the elements() buffer, the transition 12894 // No change is needed to the elements() buffer, the transition
12793 // only requires a map change. 12895 // only requires a map change.
(...skipping 1948 matching lines...) Expand 10 before | Expand all | Expand 10 after
14742 } 14844 }
14743 14845
14744 14846
14745 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { 14847 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
14746 ASSERT(!HasFastProperties()); 14848 ASSERT(!HasFastProperties());
14747 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); 14849 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
14748 return PropertyCell::cast(value); 14850 return PropertyCell::cast(value);
14749 } 14851 }
14750 14852
14751 14853
14752 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( 14854 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
14753 Handle<GlobalObject> global, 14855 Handle<JSGlobalObject> global,
14754 Handle<Name> name) { 14856 Handle<Name> name) {
14755 ASSERT(!global->HasFastProperties()); 14857 ASSERT(!global->HasFastProperties());
14756 int entry = global->property_dictionary()->FindEntry(*name); 14858 int entry = global->property_dictionary()->FindEntry(*name);
14757 if (entry == NameDictionary::kNotFound) { 14859 if (entry == NameDictionary::kNotFound) {
14758 Isolate* isolate = global->GetIsolate(); 14860 Isolate* isolate = global->GetIsolate();
14759 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( 14861 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
14760 isolate->factory()->the_hole_value()); 14862 isolate->factory()->the_hole_value());
14761 PropertyDetails details(NONE, NORMAL, 0); 14863 PropertyDetails details(NONE, NORMAL, 0);
14762 details = details.AsDeleted(); 14864 details = details.AsDeleted();
14763 Handle<NameDictionary> dictionary = NameDictionaryAdd( 14865 Handle<NameDictionary> dictionary = NameDictionaryAdd(
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
15131 15233
15132 template<typename Shape, typename Key> 15234 template<typename Shape, typename Key>
15133 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, 15235 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap,
15134 int at_least_space_for, 15236 int at_least_space_for,
15135 PretenureFlag pretenure) { 15237 PretenureFlag pretenure) {
15136 Object* obj; 15238 Object* obj;
15137 { MaybeObject* maybe_obj = 15239 { MaybeObject* maybe_obj =
15138 HashTable<Shape, Key>::Allocate( 15240 HashTable<Shape, Key>::Allocate(
15139 heap, 15241 heap,
15140 at_least_space_for, 15242 at_least_space_for,
15141 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY, 15243 USE_DEFAULT_MINIMUM_CAPACITY,
15142 pretenure); 15244 pretenure);
15143 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 15245 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
15144 } 15246 }
15145 // Initialize the next enumeration index. 15247 // Initialize the next enumeration index.
15146 Dictionary<Shape, Key>::cast(obj)-> 15248 Dictionary<Shape, Key>::cast(obj)->
15147 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); 15249 SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
15148 return obj; 15250 return obj;
15149 } 15251 }
15150 15252
15151 15253
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
15697 obj->set_properties(fields); 15799 obj->set_properties(fields);
15698 ASSERT(obj->IsJSObject()); 15800 ASSERT(obj->IsJSObject());
15699 15801
15700 // Check that it really works. 15802 // Check that it really works.
15701 ASSERT(obj->HasFastProperties()); 15803 ASSERT(obj->HasFastProperties());
15702 15804
15703 return obj; 15805 return obj;
15704 } 15806 }
15705 15807
15706 15808
15809 Handle<ObjectHashSet> ObjectHashSet::EnsureCapacity(
15810 Handle<ObjectHashSet> table,
15811 int n,
15812 Handle<Object> key,
15813 PretenureFlag pretenure) {
15814 Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table;
15815 CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15816 table_base->EnsureCapacity(n, *key, pretenure),
15817 ObjectHashSet);
15818 }
15819
15820
15821 Handle<ObjectHashSet> ObjectHashSet::Shrink(Handle<ObjectHashSet> table,
15822 Handle<Object> key) {
15823 Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table;
15824 CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15825 table_base->Shrink(*key),
15826 ObjectHashSet);
15827 }
15828
15829
15707 bool ObjectHashSet::Contains(Object* key) { 15830 bool ObjectHashSet::Contains(Object* key) {
15708 ASSERT(IsKey(key)); 15831 ASSERT(IsKey(key));
15709 15832
15710 // If the object does not have an identity hash, it was never used as a key. 15833 // If the object does not have an identity hash, it was never used as a key.
15711 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); 15834 Object* hash = key->GetHash();
15712 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false; 15835 if (hash->IsUndefined()) return false;
15713 } 15836
15714 return (FindEntry(key) != kNotFound); 15837 return (FindEntry(key) != kNotFound);
15715 } 15838 }
15716 15839
15717 15840
15718 MaybeObject* ObjectHashSet::Add(Object* key) { 15841 Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> table,
15719 ASSERT(IsKey(key)); 15842 Handle<Object> key) {
15843 ASSERT(table->IsKey(*key));
15720 15844
15721 // Make sure the key object has an identity hash code. 15845 // Make sure the key object has an identity hash code.
15722 int hash; 15846 Handle<Object> object_hash = Object::GetOrCreateHash(key,
15723 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); 15847 table->GetIsolate());
15724 if (maybe_hash->IsFailure()) return maybe_hash; 15848
15725 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); 15849 int entry = table->FindEntry(*key);
15726 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
15727 }
15728 int entry = FindEntry(key);
15729 15850
15730 // Check whether key is already present. 15851 // Check whether key is already present.
15731 if (entry != kNotFound) return this; 15852 if (entry != kNotFound) return table;
15732 15853
15733 // Check whether the hash set should be extended and add entry. 15854 // Check whether the hash set should be extended and add entry.
15734 Object* obj; 15855 Handle<ObjectHashSet> new_table =
15735 { MaybeObject* maybe_obj = EnsureCapacity(1, key); 15856 ObjectHashSet::EnsureCapacity(table, 1, key);
15736 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 15857 entry = new_table->FindInsertionEntry(Smi::cast(*object_hash)->value());
15737 } 15858 new_table->set(EntryToIndex(entry), *key);
15738 ObjectHashSet* table = ObjectHashSet::cast(obj); 15859 new_table->ElementAdded();
15739 entry = table->FindInsertionEntry(hash); 15860 return new_table;
15740 table->set(EntryToIndex(entry), key);
15741 table->ElementAdded();
15742 return table;
15743 } 15861 }
15744 15862
15745 15863
15746 MaybeObject* ObjectHashSet::Remove(Object* key) { 15864 Handle<ObjectHashSet> ObjectHashSet::Remove(Handle<ObjectHashSet> table,
15747 ASSERT(IsKey(key)); 15865 Handle<Object> key) {
15866 ASSERT(table->IsKey(*key));
15748 15867
15749 // If the object does not have an identity hash, it was never used as a key. 15868 // If the object does not have an identity hash, it was never used as a key.
15750 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); 15869 if (key->GetHash()->IsUndefined()) return table;
15751 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this; 15870
15752 } 15871 int entry = table->FindEntry(*key);
15753 int entry = FindEntry(key);
15754 15872
15755 // Check whether key is actually present. 15873 // Check whether key is actually present.
15756 if (entry == kNotFound) return this; 15874 if (entry == kNotFound) return table;
15757 15875
15758 // Remove entry and try to shrink this hash set. 15876 // Remove entry and try to shrink this hash set.
15759 set_the_hole(EntryToIndex(entry)); 15877 table->set_the_hole(EntryToIndex(entry));
15760 ElementRemoved(); 15878 table->ElementRemoved();
15761 return Shrink(key); 15879
15880 return ObjectHashSet::Shrink(table, key);
15762 } 15881 }
15763 15882
15764 15883
15884 Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity(
15885 Handle<ObjectHashTable> table,
15886 int n,
15887 Handle<Object> key,
15888 PretenureFlag pretenure) {
15889 Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table;
15890 CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15891 table_base->EnsureCapacity(n, *key, pretenure),
15892 ObjectHashTable);
15893 }
15894
15895
15896 Handle<ObjectHashTable> ObjectHashTable::Shrink(
15897 Handle<ObjectHashTable> table, Handle<Object> key) {
15898 Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table;
15899 CALL_HEAP_FUNCTION(table_base->GetIsolate(),
15900 table_base->Shrink(*key),
15901 ObjectHashTable);
15902 }
15903
15904
15765 Object* ObjectHashTable::Lookup(Object* key) { 15905 Object* ObjectHashTable::Lookup(Object* key) {
15766 ASSERT(IsKey(key)); 15906 ASSERT(IsKey(key));
15767 15907
15768 // If the object does not have an identity hash, it was never used as a key. 15908 // If the object does not have an identity hash, it was never used as a key.
15769 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); 15909 Object* hash = key->GetHash();
15770 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) { 15910 if (hash->IsUndefined()) {
15771 return GetHeap()->the_hole_value(); 15911 return GetHeap()->the_hole_value();
15772 }
15773 } 15912 }
15774 int entry = FindEntry(key); 15913 int entry = FindEntry(key);
15775 if (entry == kNotFound) return GetHeap()->the_hole_value(); 15914 if (entry == kNotFound) return GetHeap()->the_hole_value();
15776 return get(EntryToIndex(entry) + 1); 15915 return get(EntryToIndex(entry) + 1);
15777 } 15916 }
15778 15917
15779 15918
15780 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { 15919 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
15781 ASSERT(IsKey(key)); 15920 Handle<Object> key,
15921 Handle<Object> value) {
15922 ASSERT(table->IsKey(*key));
15923
15924 Isolate* isolate = table->GetIsolate();
15782 15925
15783 // Make sure the key object has an identity hash code. 15926 // Make sure the key object has an identity hash code.
15784 int hash; 15927 Handle<Object> hash = Object::GetOrCreateHash(key, isolate);
15785 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); 15928
15786 if (maybe_hash->IsFailure()) return maybe_hash; 15929 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 15930
15792 // Check whether to perform removal operation. 15931 // Check whether to perform removal operation.
15793 if (value->IsTheHole()) { 15932 if (value->IsTheHole()) {
15794 if (entry == kNotFound) return this; 15933 if (entry == kNotFound) return table;
15795 RemoveEntry(entry); 15934 table->RemoveEntry(entry);
15796 return Shrink(key); 15935 return Shrink(table, key);
15797 } 15936 }
15798 15937
15799 // Key is already in table, just overwrite value. 15938 // Key is already in table, just overwrite value.
15800 if (entry != kNotFound) { 15939 if (entry != kNotFound) {
15801 set(EntryToIndex(entry) + 1, value); 15940 table->set(EntryToIndex(entry) + 1, *value);
15802 return this; 15941 return table;
15803 } 15942 }
15804 15943
15805 // Check whether the hash table should be extended. 15944 // Check whether the hash table should be extended.
15806 Object* obj; 15945 table = EnsureCapacity(table, 1, key);
15807 { MaybeObject* maybe_obj = EnsureCapacity(1, key); 15946 table->AddEntry(table->FindInsertionEntry(Handle<Smi>::cast(hash)->value()),
15808 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 15947 *key,
15809 } 15948 *value);
15810 ObjectHashTable* table = ObjectHashTable::cast(obj);
15811 table->AddEntry(table->FindInsertionEntry(hash), key, value);
15812 return table; 15949 return table;
15813 } 15950 }
15814 15951
15815 15952
15816 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { 15953 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
15817 set(EntryToIndex(entry), key); 15954 set(EntryToIndex(entry), key);
15818 set(EntryToIndex(entry) + 1, value); 15955 set(EntryToIndex(entry) + 1, value);
15819 ElementAdded(); 15956 ElementAdded();
15820 } 15957 }
15821 15958
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
16396 #define ERROR_MESSAGES_TEXTS(C, T) T, 16533 #define ERROR_MESSAGES_TEXTS(C, T) T,
16397 static const char* error_messages_[] = { 16534 static const char* error_messages_[] = {
16398 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16535 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16399 }; 16536 };
16400 #undef ERROR_MESSAGES_TEXTS 16537 #undef ERROR_MESSAGES_TEXTS
16401 return error_messages_[reason]; 16538 return error_messages_[reason];
16402 } 16539 }
16403 16540
16404 16541
16405 } } // namespace v8::internal 16542 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698