| 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()); |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |