| 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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 return GetPrimitiveValue(data->primitive_value_descriptor, | 336 return GetPrimitiveValue(data->primitive_value_descriptor, |
| 337 current, | 337 current, |
| 338 isolate->heap()); | 338 isolate->heap()); |
| 339 } | 339 } |
| 340 } | 340 } |
| 341 UNREACHABLE(); | 341 UNREACHABLE(); |
| 342 return NULL; | 342 return NULL; |
| 343 } | 343 } |
| 344 | 344 |
| 345 | 345 |
| 346 Handle<FixedArray> JSObject::EnsureWritableFastElements( |
| 347 Handle<JSObject> object) { |
| 348 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 349 object->EnsureWritableFastElements(), |
| 350 FixedArray); |
| 351 } |
| 352 |
| 353 |
| 346 Handle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object, | 354 Handle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object, |
| 347 Handle<Object> receiver, | 355 Handle<Object> receiver, |
| 348 Handle<Object> structure, | 356 Handle<Object> structure, |
| 349 Handle<Name> name) { | 357 Handle<Name> name) { |
| 350 Isolate* isolate = name->GetIsolate(); | 358 Isolate* isolate = name->GetIsolate(); |
| 351 // To accommodate both the old and the new api we switch on the | 359 // To accommodate both the old and the new api we switch on the |
| 352 // data structure used to store the callbacks. Eventually foreign | 360 // data structure used to store the callbacks. Eventually foreign |
| 353 // callbacks should be phased out. | 361 // callbacks should be phased out. |
| 354 if (structure->IsForeign()) { | 362 if (structure->IsForeign()) { |
| 355 AccessorDescriptor* callback = | 363 AccessorDescriptor* callback = |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 return context->symbol_function()->instance_prototype(); | 1021 return context->symbol_function()->instance_prototype(); |
| 1014 } | 1022 } |
| 1015 if (heap_object->IsBoolean()) { | 1023 if (heap_object->IsBoolean()) { |
| 1016 return context->boolean_function()->instance_prototype(); | 1024 return context->boolean_function()->instance_prototype(); |
| 1017 } else { | 1025 } else { |
| 1018 return isolate->heap()->null_value(); | 1026 return isolate->heap()->null_value(); |
| 1019 } | 1027 } |
| 1020 } | 1028 } |
| 1021 | 1029 |
| 1022 | 1030 |
| 1023 MaybeObject* Object::GetHash(CreationFlag flag) { | 1031 Object* Object::GetHash() { |
| 1024 // The object is either a number, a name, an odd-ball, | 1032 // The object is either a number, a name, an odd-ball, |
| 1025 // a real JS object, or a Harmony proxy. | 1033 // a real JS object, or a Harmony proxy. |
| 1026 if (IsNumber()) { | 1034 if (IsNumber()) { |
| 1027 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); | 1035 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); |
| 1028 return Smi::FromInt(hash & Smi::kMaxValue); | 1036 return Smi::FromInt(hash & Smi::kMaxValue); |
| 1029 } | 1037 } |
| 1030 if (IsName()) { | 1038 if (IsName()) { |
| 1031 uint32_t hash = Name::cast(this)->Hash(); | 1039 uint32_t hash = Name::cast(this)->Hash(); |
| 1032 return Smi::FromInt(hash); | 1040 return Smi::FromInt(hash); |
| 1033 } | 1041 } |
| 1034 if (IsOddball()) { | 1042 if (IsOddball()) { |
| 1035 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); | 1043 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
| 1036 return Smi::FromInt(hash); | 1044 return Smi::FromInt(hash); |
| 1037 } | 1045 } |
| 1038 if (IsJSReceiver()) { | |
| 1039 return JSReceiver::cast(this)->GetIdentityHash(flag); | |
| 1040 } | |
| 1041 | 1046 |
| 1042 UNREACHABLE(); | 1047 ASSERT(IsJSReceiver()); |
| 1043 return Smi::FromInt(0); | 1048 return JSReceiver::cast(this)->GetIdentityHash(); |
| 1044 } | 1049 } |
| 1045 | 1050 |
| 1046 | 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 |
| 1047 bool Object::SameValue(Object* other) { | 1063 bool Object::SameValue(Object* other) { |
| 1048 if (other == this) return true; | 1064 if (other == this) return true; |
| 1049 | 1065 |
| 1050 // The object is either a number, a name, an odd-ball, | 1066 // The object is either a number, a name, an odd-ball, |
| 1051 // a real JS object, or a Harmony proxy. | 1067 // a real JS object, or a Harmony proxy. |
| 1052 if (IsNumber() && other->IsNumber()) { | 1068 if (IsNumber() && other->IsNumber()) { |
| 1053 double this_value = Number(); | 1069 double this_value = Number(); |
| 1054 double other_value = other->Number(); | 1070 double other_value = other->Number(); |
| 1055 bool equal = this_value == other_value; | 1071 bool equal = this_value == other_value; |
| 1056 // SameValue(NaN, NaN) is true. | 1072 // SameValue(NaN, NaN) is true. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 default: | 1205 default: |
| 1190 return this; | 1206 return this; |
| 1191 } | 1207 } |
| 1192 } | 1208 } |
| 1193 | 1209 |
| 1194 | 1210 |
| 1195 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 1211 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 1196 // Externalizing twice leaks the external resource, so it's | 1212 // Externalizing twice leaks the external resource, so it's |
| 1197 // prohibited by the API. | 1213 // prohibited by the API. |
| 1198 ASSERT(!this->IsExternalString()); | 1214 ASSERT(!this->IsExternalString()); |
| 1199 #ifdef DEBUG | 1215 #ifdef ENABLE_SLOW_ASSERTS |
| 1200 if (FLAG_enable_slow_asserts) { | 1216 if (FLAG_enable_slow_asserts) { |
| 1201 // Assert that the resource and the string are equivalent. | 1217 // Assert that the resource and the string are equivalent. |
| 1202 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 1218 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 1203 ScopedVector<uc16> smart_chars(this->length()); | 1219 ScopedVector<uc16> smart_chars(this->length()); |
| 1204 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1220 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1205 ASSERT(memcmp(smart_chars.start(), | 1221 ASSERT(memcmp(smart_chars.start(), |
| 1206 resource->data(), | 1222 resource->data(), |
| 1207 resource->length() * sizeof(smart_chars[0])) == 0); | 1223 resource->length() * sizeof(smart_chars[0])) == 0); |
| 1208 } | 1224 } |
| 1209 #endif // DEBUG | 1225 #endif // DEBUG |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); | 1262 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); |
| 1247 if (Marking::IsBlack(Marking::MarkBitFrom(this))) { | 1263 if (Marking::IsBlack(Marking::MarkBitFrom(this))) { |
| 1248 MemoryChunk::IncrementLiveBytesFromMutator(this->address(), | 1264 MemoryChunk::IncrementLiveBytesFromMutator(this->address(), |
| 1249 new_size - size); | 1265 new_size - size); |
| 1250 } | 1266 } |
| 1251 return true; | 1267 return true; |
| 1252 } | 1268 } |
| 1253 | 1269 |
| 1254 | 1270 |
| 1255 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { | 1271 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
| 1256 #ifdef DEBUG | 1272 #ifdef ENABLE_SLOW_ASSERTS |
| 1257 if (FLAG_enable_slow_asserts) { | 1273 if (FLAG_enable_slow_asserts) { |
| 1258 // Assert that the resource and the string are equivalent. | 1274 // Assert that the resource and the string are equivalent. |
| 1259 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 1275 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 1260 if (this->IsTwoByteRepresentation()) { | 1276 if (this->IsTwoByteRepresentation()) { |
| 1261 ScopedVector<uint16_t> smart_chars(this->length()); | 1277 ScopedVector<uint16_t> smart_chars(this->length()); |
| 1262 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1278 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 1263 ASSERT(String::IsOneByte(smart_chars.start(), this->length())); | 1279 ASSERT(String::IsOneByte(smart_chars.start(), this->length())); |
| 1264 } | 1280 } |
| 1265 ScopedVector<char> smart_chars(this->length()); | 1281 ScopedVector<char> smart_chars(this->length()); |
| 1266 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 1282 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2134 AddSlowProperty(object, name, value, attributes); | 2150 AddSlowProperty(object, name, value, attributes); |
| 2135 } | 2151 } |
| 2136 } else { | 2152 } else { |
| 2137 AddSlowProperty(object, name, value, attributes); | 2153 AddSlowProperty(object, name, value, attributes); |
| 2138 } | 2154 } |
| 2139 | 2155 |
| 2140 if (FLAG_harmony_observation && | 2156 if (FLAG_harmony_observation && |
| 2141 object->map()->is_observed() && | 2157 object->map()->is_observed() && |
| 2142 *name != isolate->heap()->hidden_string()) { | 2158 *name != isolate->heap()->hidden_string()) { |
| 2143 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 2159 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 2144 EnqueueChangeRecord(object, "new", name, old_value); | 2160 EnqueueChangeRecord(object, "add", name, old_value); |
| 2145 } | 2161 } |
| 2146 | 2162 |
| 2147 return value; | 2163 return value; |
| 2148 } | 2164 } |
| 2149 | 2165 |
| 2150 | 2166 |
| 2151 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2167 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| 2152 const char* type_str, | 2168 const char* type_str, |
| 2153 Handle<Name> name, | 2169 Handle<Name> name, |
| 2154 Handle<Object> old_value) { | 2170 Handle<Object> old_value) { |
| 2155 Isolate* isolate = object->GetIsolate(); | 2171 Isolate* isolate = object->GetIsolate(); |
| 2156 HandleScope scope(isolate); | 2172 HandleScope scope(isolate); |
| 2157 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); | 2173 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); |
| 2158 if (object->IsJSGlobalObject()) { | 2174 if (object->IsJSGlobalObject()) { |
| 2159 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); | 2175 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); |
| 2160 } | 2176 } |
| 2161 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; |
| 2162 bool threw; | 2179 bool threw; |
| 2180 |
| 2163 Execution::Call(isolate, | 2181 Execution::Call(isolate, |
| 2164 Handle<JSFunction>(isolate->observers_notify_change()), | 2182 Handle<JSFunction>(isolate->observers_notify_change()), |
| 2165 isolate->factory()->undefined_value(), | 2183 isolate->factory()->undefined_value(), |
| 2166 old_value->IsTheHole() ? 3 : 4, args, | 2184 argc, args, |
| 2167 &threw); | 2185 &threw); |
| 2168 ASSERT(!threw); | 2186 ASSERT(!threw); |
| 2169 } | 2187 } |
| 2170 | 2188 |
| 2171 | 2189 |
| 2172 void JSObject::DeliverChangeRecords(Isolate* isolate) { | 2190 void JSObject::DeliverChangeRecords(Isolate* isolate) { |
| 2173 ASSERT(isolate->observer_delivery_pending()); | 2191 ASSERT(isolate->observer_delivery_pending()); |
| 2174 bool threw = false; | 2192 bool threw = false; |
| 2175 Execution::Call( | 2193 Execution::Call( |
| 2176 isolate, | 2194 isolate, |
| (...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3740 Handle<JSReceiver> receiver(receiver_raw); | 3758 Handle<JSReceiver> receiver(receiver_raw); |
| 3741 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3759 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 3742 return proxy->GetPropertyAttributeWithHandler(*receiver, *name); | 3760 return proxy->GetPropertyAttributeWithHandler(*receiver, *name); |
| 3743 } | 3761 } |
| 3744 | 3762 |
| 3745 | 3763 |
| 3746 void JSProxy::Fix(Handle<JSProxy> proxy) { | 3764 void JSProxy::Fix(Handle<JSProxy> proxy) { |
| 3747 Isolate* isolate = proxy->GetIsolate(); | 3765 Isolate* isolate = proxy->GetIsolate(); |
| 3748 | 3766 |
| 3749 // Save identity hash. | 3767 // Save identity hash. |
| 3750 Handle<Object> hash = JSProxy::GetIdentityHash(proxy, OMIT_CREATION); | 3768 Handle<Object> hash(proxy->GetIdentityHash(), isolate); |
| 3751 | 3769 |
| 3752 if (proxy->IsJSFunctionProxy()) { | 3770 if (proxy->IsJSFunctionProxy()) { |
| 3753 isolate->factory()->BecomeJSFunction(proxy); | 3771 isolate->factory()->BecomeJSFunction(proxy); |
| 3754 // Code will be set on the JavaScript side. | 3772 // Code will be set on the JavaScript side. |
| 3755 } else { | 3773 } else { |
| 3756 isolate->factory()->BecomeJSObject(proxy); | 3774 isolate->factory()->BecomeJSObject(proxy); |
| 3757 } | 3775 } |
| 3758 ASSERT(proxy->IsJSObject()); | 3776 ASSERT(proxy->IsJSObject()); |
| 3759 | 3777 |
| 3760 // Inherit identity, if it was present. | 3778 // Inherit identity, if it was present. |
| 3761 if (hash->IsSmi()) { | 3779 if (hash->IsSmi()) { |
| 3762 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), Smi::cast(*hash)); | 3780 JSObject::SetIdentityHash(Handle<JSObject>::cast(proxy), |
| 3781 Handle<Smi>::cast(hash)); |
| 3763 } | 3782 } |
| 3764 } | 3783 } |
| 3765 | 3784 |
| 3766 | 3785 |
| 3767 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, | 3786 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name, |
| 3768 Handle<Object> derived, | 3787 Handle<Object> derived, |
| 3769 int argc, | 3788 int argc, |
| 3770 Handle<Object> argv[]) { | 3789 Handle<Object> argv[]) { |
| 3771 Isolate* isolate = GetIsolate(); | 3790 Isolate* isolate = GetIsolate(); |
| 3772 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... |
| 4079 break; | 4098 break; |
| 4080 case HANDLER: | 4099 case HANDLER: |
| 4081 case NONEXISTENT: | 4100 case NONEXISTENT: |
| 4082 UNREACHABLE(); | 4101 UNREACHABLE(); |
| 4083 } | 4102 } |
| 4084 | 4103 |
| 4085 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); | 4104 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 4086 | 4105 |
| 4087 if (is_observed) { | 4106 if (is_observed) { |
| 4088 if (lookup->IsTransition()) { | 4107 if (lookup->IsTransition()) { |
| 4089 EnqueueChangeRecord(object, "new", name, old_value); | 4108 EnqueueChangeRecord(object, "add", name, old_value); |
| 4090 } else { | 4109 } else { |
| 4091 LookupResult new_lookup(isolate); | 4110 LookupResult new_lookup(isolate); |
| 4092 object->LocalLookup(*name, &new_lookup, true); | 4111 object->LocalLookup(*name, &new_lookup, true); |
| 4093 if (new_lookup.IsDataProperty()) { | 4112 if (new_lookup.IsDataProperty()) { |
| 4094 Handle<Object> new_value = Object::GetProperty(object, name); | 4113 Handle<Object> new_value = Object::GetProperty(object, name); |
| 4095 if (!new_value->SameValue(*old_value)) { | 4114 if (!new_value->SameValue(*old_value)) { |
| 4096 EnqueueChangeRecord(object, "updated", name, old_value); | 4115 EnqueueChangeRecord(object, "update", name, old_value); |
| 4097 } | 4116 } |
| 4098 } | 4117 } |
| 4099 } | 4118 } |
| 4100 } | 4119 } |
| 4101 | 4120 |
| 4102 return result; | 4121 return result; |
| 4103 } | 4122 } |
| 4104 | 4123 |
| 4105 | 4124 |
| 4106 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( | |
| 4107 Name* key, | |
| 4108 Object* value, | |
| 4109 PropertyAttributes attributes, | |
| 4110 ValueType value_type, | |
| 4111 StoreMode mode, | |
| 4112 ExtensibilityCheck extensibility_check) { | |
| 4113 // TODO(mstarzinger): The trampoline is a giant hack, don't use it anywhere | |
| 4114 // else or handlification people will start hating you for all eternity. | |
| 4115 HandleScope scope(GetIsolate()); | |
| 4116 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); | |
| 4117 return trampoline.CallWithReturnValue( | |
| 4118 &JSObject::SetLocalPropertyIgnoreAttributes, | |
| 4119 Handle<JSObject>(this), | |
| 4120 Handle<Name>(key), | |
| 4121 Handle<Object>(value, GetIsolate()), | |
| 4122 attributes, | |
| 4123 value_type, | |
| 4124 mode, | |
| 4125 extensibility_check); | |
| 4126 } | |
| 4127 | |
| 4128 | |
| 4129 // 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 |
| 4130 // 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 |
| 4131 // SetProperty, with the check for IsReadOnly and the check for a | 4127 // SetProperty, with the check for IsReadOnly and the check for a |
| 4132 // callback setter removed. The two lines looking up the LookupResult | 4128 // callback setter removed. The two lines looking up the LookupResult |
| 4133 // 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 |
| 4134 // should be. | 4130 // should be. |
| 4135 // 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 |
| 4136 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" | 4132 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
| 4137 // doesn't handle function prototypes correctly. | 4133 // doesn't handle function prototypes correctly. |
| 4138 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( | 4134 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4219 break; | 4215 break; |
| 4220 } | 4216 } |
| 4221 case NONEXISTENT: | 4217 case NONEXISTENT: |
| 4222 case HANDLER: | 4218 case HANDLER: |
| 4223 case INTERCEPTOR: | 4219 case INTERCEPTOR: |
| 4224 UNREACHABLE(); | 4220 UNREACHABLE(); |
| 4225 } | 4221 } |
| 4226 | 4222 |
| 4227 if (is_observed) { | 4223 if (is_observed) { |
| 4228 if (lookup.IsTransition()) { | 4224 if (lookup.IsTransition()) { |
| 4229 EnqueueChangeRecord(object, "new", name, old_value); | 4225 EnqueueChangeRecord(object, "add", name, old_value); |
| 4230 } else if (old_value->IsTheHole()) { | 4226 } else if (old_value->IsTheHole()) { |
| 4231 EnqueueChangeRecord(object, "reconfigured", name, old_value); | 4227 EnqueueChangeRecord(object, "reconfigure", name, old_value); |
| 4232 } else { | 4228 } else { |
| 4233 LookupResult new_lookup(isolate); | 4229 LookupResult new_lookup(isolate); |
| 4234 object->LocalLookup(*name, &new_lookup, true); | 4230 object->LocalLookup(*name, &new_lookup, true); |
| 4235 bool value_changed = false; | 4231 bool value_changed = false; |
| 4236 if (new_lookup.IsDataProperty()) { | 4232 if (new_lookup.IsDataProperty()) { |
| 4237 Handle<Object> new_value = Object::GetProperty(object, name); | 4233 Handle<Object> new_value = Object::GetProperty(object, name); |
| 4238 value_changed = !old_value->SameValue(*new_value); | 4234 value_changed = !old_value->SameValue(*new_value); |
| 4239 } | 4235 } |
| 4240 if (new_lookup.GetAttributes() != old_attributes) { | 4236 if (new_lookup.GetAttributes() != old_attributes) { |
| 4241 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 4237 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
| 4242 EnqueueChangeRecord(object, "reconfigured", name, old_value); | 4238 EnqueueChangeRecord(object, "reconfigure", name, old_value); |
| 4243 } else if (value_changed) { | 4239 } else if (value_changed) { |
| 4244 EnqueueChangeRecord(object, "updated", name, old_value); | 4240 EnqueueChangeRecord(object, "update", name, old_value); |
| 4245 } | 4241 } |
| 4246 } | 4242 } |
| 4247 } | 4243 } |
| 4248 | 4244 |
| 4249 return value; | 4245 return value; |
| 4250 } | 4246 } |
| 4251 | 4247 |
| 4252 | 4248 |
| 4253 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 4249 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
| 4254 JSObject* receiver, | 4250 JSObject* receiver, |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4476 int index = obj->map()->Hash() % kEntries; | 4472 int index = obj->map()->Hash() % kEntries; |
| 4477 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); | 4473 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); |
| 4478 if (result->IsMap() && | 4474 if (result->IsMap() && |
| 4479 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), | 4475 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), |
| 4480 mode)) { | 4476 mode)) { |
| 4481 #ifdef VERIFY_HEAP | 4477 #ifdef VERIFY_HEAP |
| 4482 if (FLAG_verify_heap) { | 4478 if (FLAG_verify_heap) { |
| 4483 Handle<Map>::cast(result)->SharedMapVerify(); | 4479 Handle<Map>::cast(result)->SharedMapVerify(); |
| 4484 } | 4480 } |
| 4485 #endif | 4481 #endif |
| 4486 #ifdef DEBUG | 4482 #ifdef ENABLE_SLOW_ASSERTS |
| 4487 if (FLAG_enable_slow_asserts) { | 4483 if (FLAG_enable_slow_asserts) { |
| 4488 // The cached map should match newly created normalized map bit-by-bit, | 4484 // The cached map should match newly created normalized map bit-by-bit, |
| 4489 // except for the code cache, which can contain some ics which can be | 4485 // except for the code cache, which can contain some ics which can be |
| 4490 // applied to the shared map. | 4486 // applied to the shared map. |
| 4491 Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode, | 4487 Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode, |
| 4492 SHARED_NORMALIZED_MAP); | 4488 SHARED_NORMALIZED_MAP); |
| 4493 | 4489 |
| 4494 ASSERT(memcmp(fresh->address(), | 4490 ASSERT(memcmp(fresh->address(), |
| 4495 Handle<Map>::cast(result)->address(), | 4491 Handle<Map>::cast(result)->address(), |
| 4496 Map::kCodeCacheOffset) == 0); | 4492 Map::kCodeCacheOffset) == 0); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4773 // within a smi. | 4769 // within a smi. |
| 4774 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; | 4770 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; |
| 4775 attempts++; | 4771 attempts++; |
| 4776 } while (hash_value == 0 && attempts < 30); | 4772 } while (hash_value == 0 && attempts < 30); |
| 4777 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 4773 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 4778 | 4774 |
| 4779 return Smi::FromInt(hash_value); | 4775 return Smi::FromInt(hash_value); |
| 4780 } | 4776 } |
| 4781 | 4777 |
| 4782 | 4778 |
| 4783 void JSObject::SetIdentityHash(Handle<JSObject> object, Smi* hash) { | 4779 void JSObject::SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash) { |
| 4784 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 4780 Isolate* isolate = object->GetIsolate(); |
| 4785 object->SetHiddenProperty( | 4781 SetHiddenProperty(object, isolate->factory()->identity_hash_string(), hash); |
| 4786 object->GetHeap()->identity_hash_string(), hash)); | |
| 4787 } | 4782 } |
| 4788 | 4783 |
| 4789 | 4784 |
| 4790 int JSObject::GetIdentityHash(Handle<JSObject> object) { | 4785 Object* JSObject::GetIdentityHash() { |
| 4791 CALL_AND_RETRY_OR_DIE(object->GetIsolate(), | 4786 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string()); |
| 4792 object->GetIdentityHash(ALLOW_CREATION), | 4787 return stored_value->IsSmi() ? stored_value : GetHeap()->undefined_value(); |
| 4793 return Smi::cast(__object__)->value(), | |
| 4794 return 0); | |
| 4795 } | 4788 } |
| 4796 | 4789 |
| 4797 | 4790 |
| 4798 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { | 4791 Handle<Object> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) { |
| 4799 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string()); | 4792 Handle<Object> hash(object->GetIdentityHash(), object->GetIsolate()); |
| 4800 if (stored_value->IsSmi()) return stored_value; | 4793 if (hash->IsSmi()) |
| 4794 return hash; |
| 4801 | 4795 |
| 4802 // Do not generate permanent identity hash code if not requested. | 4796 Isolate* isolate = object->GetIsolate(); |
| 4803 if (flag == OMIT_CREATION) return GetHeap()->undefined_value(); | |
| 4804 | 4797 |
| 4805 Smi* hash = GenerateIdentityHash(); | 4798 hash = handle(object->GenerateIdentityHash(), isolate); |
| 4806 MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_string(), | 4799 Handle<Object> result = SetHiddenProperty(object, |
| 4807 hash); | 4800 isolate->factory()->identity_hash_string(), hash); |
| 4808 if (result->IsFailure()) return result; | 4801 |
| 4809 if (result->ToObjectUnchecked()->IsUndefined()) { | 4802 if (result->IsUndefined()) { |
| 4810 // Trying to get hash of detached proxy. | 4803 // Trying to get hash of detached proxy. |
| 4811 return Smi::FromInt(0); | 4804 return handle(Smi::FromInt(0), isolate); |
| 4812 } | 4805 } |
| 4806 |
| 4813 return hash; | 4807 return hash; |
| 4814 } | 4808 } |
| 4815 | 4809 |
| 4816 | 4810 |
| 4817 Handle<Object> JSProxy::GetIdentityHash(Handle<JSProxy> proxy, | 4811 Object* JSProxy::GetIdentityHash() { |
| 4818 CreationFlag flag) { | 4812 return this->hash(); |
| 4819 CALL_HEAP_FUNCTION(proxy->GetIsolate(), proxy->GetIdentityHash(flag), Object); | |
| 4820 } | 4813 } |
| 4821 | 4814 |
| 4822 | 4815 |
| 4823 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) { | 4816 Handle<Object> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) { |
| 4824 Object* hash = this->hash(); | 4817 Isolate* isolate = proxy->GetIsolate(); |
| 4825 if (!hash->IsSmi() && flag == ALLOW_CREATION) { | 4818 |
| 4826 hash = GenerateIdentityHash(); | 4819 Handle<Object> hash(proxy->GetIdentityHash(), isolate); |
| 4827 set_hash(hash); | 4820 if (hash->IsSmi()) |
| 4828 } | 4821 return hash; |
| 4822 |
| 4823 hash = handle(proxy->GenerateIdentityHash(), isolate); |
| 4824 proxy->set_hash(*hash); |
| 4829 return hash; | 4825 return hash; |
| 4830 } | 4826 } |
| 4831 | 4827 |
| 4832 | 4828 |
| 4833 Object* JSObject::GetHiddenProperty(Name* key) { | 4829 Object* JSObject::GetHiddenProperty(Name* key) { |
| 4834 ASSERT(key->IsUniqueName()); | 4830 ASSERT(key->IsUniqueName()); |
| 4835 if (IsJSGlobalProxy()) { | 4831 if (IsJSGlobalProxy()) { |
| 4836 // For a proxy, use the prototype as target object. | 4832 // For a proxy, use the prototype as target object. |
| 4837 Object* proxy_parent = GetPrototype(); | 4833 Object* proxy_parent = GetPrototype(); |
| 4838 // If the proxy is detached, return undefined. | 4834 // If the proxy is detached, return undefined. |
| 4839 if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); | 4835 if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); |
| 4840 ASSERT(proxy_parent->IsJSGlobalObject()); | 4836 ASSERT(proxy_parent->IsJSGlobalObject()); |
| 4841 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); | 4837 return JSObject::cast(proxy_parent)->GetHiddenProperty(key); |
| 4842 } | 4838 } |
| 4843 ASSERT(!IsJSGlobalProxy()); | 4839 ASSERT(!IsJSGlobalProxy()); |
| 4844 MaybeObject* hidden_lookup = | 4840 Object* inline_value = GetHiddenPropertiesHashTable(); |
| 4845 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); | |
| 4846 Object* inline_value = hidden_lookup->ToObjectUnchecked(); | |
| 4847 | 4841 |
| 4848 if (inline_value->IsSmi()) { | 4842 if (inline_value->IsSmi()) { |
| 4849 // Handle inline-stored identity hash. | 4843 // Handle inline-stored identity hash. |
| 4850 if (key == GetHeap()->identity_hash_string()) { | 4844 if (key == GetHeap()->identity_hash_string()) { |
| 4851 return inline_value; | 4845 return inline_value; |
| 4852 } else { | 4846 } else { |
| 4853 return GetHeap()->the_hole_value(); | 4847 return GetHeap()->the_hole_value(); |
| 4854 } | 4848 } |
| 4855 } | 4849 } |
| 4856 | 4850 |
| 4857 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | 4851 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
| 4858 | 4852 |
| 4859 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | 4853 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
| 4860 Object* entry = hashtable->Lookup(key); | 4854 Object* entry = hashtable->Lookup(key); |
| 4861 return entry; | 4855 return entry; |
| 4862 } | 4856 } |
| 4863 | 4857 |
| 4864 | 4858 |
| 4865 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, | 4859 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
| 4866 Handle<Name> key, | 4860 Handle<Name> key, |
| 4867 Handle<Object> value) { | 4861 Handle<Object> value) { |
| 4868 CALL_HEAP_FUNCTION(obj->GetIsolate(), | 4862 Isolate* isolate = object->GetIsolate(); |
| 4869 obj->SetHiddenProperty(*key, *value), | 4863 |
| 4870 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; |
| 4871 } | 4898 } |
| 4872 | 4899 |
| 4873 | 4900 |
| 4874 MaybeObject* JSObject::SetHiddenProperty(Name* key, Object* value) { | |
| 4875 ASSERT(key->IsUniqueName()); | |
| 4876 if (IsJSGlobalProxy()) { | |
| 4877 // For a proxy, use the prototype as target object. | |
| 4878 Object* proxy_parent = GetPrototype(); | |
| 4879 // If the proxy is detached, return undefined. | |
| 4880 if (proxy_parent->IsNull()) return GetHeap()->undefined_value(); | |
| 4881 ASSERT(proxy_parent->IsJSGlobalObject()); | |
| 4882 return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value); | |
| 4883 } | |
| 4884 ASSERT(!IsJSGlobalProxy()); | |
| 4885 MaybeObject* hidden_lookup = | |
| 4886 GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); | |
| 4887 Object* inline_value = hidden_lookup->ToObjectUnchecked(); | |
| 4888 | |
| 4889 // If there is no backing store yet, store the identity hash inline. | |
| 4890 if (value->IsSmi() && | |
| 4891 key == GetHeap()->identity_hash_string() && | |
| 4892 (inline_value->IsUndefined() || inline_value->IsSmi())) { | |
| 4893 return SetHiddenPropertiesHashTable(value); | |
| 4894 } | |
| 4895 | |
| 4896 hidden_lookup = GetHiddenPropertiesHashTable(CREATE_NEW_IF_ABSENT); | |
| 4897 ObjectHashTable* hashtable; | |
| 4898 if (!hidden_lookup->To(&hashtable)) return hidden_lookup; | |
| 4899 | |
| 4900 // If it was found, check if the key is already in the dictionary. | |
| 4901 MaybeObject* insert_result = hashtable->Put(key, value); | |
| 4902 ObjectHashTable* new_table; | |
| 4903 if (!insert_result->To(&new_table)) return insert_result; | |
| 4904 if (new_table != hashtable) { | |
| 4905 // If adding the key expanded the dictionary (i.e., Add returned a new | |
| 4906 // dictionary), store it back to the object. | |
| 4907 MaybeObject* store_result = SetHiddenPropertiesHashTable(new_table); | |
| 4908 if (store_result->IsFailure()) return store_result; | |
| 4909 } | |
| 4910 // Return this to mark success. | |
| 4911 return this; | |
| 4912 } | |
| 4913 | |
| 4914 | |
| 4915 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { | 4901 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { |
| 4916 Isolate* isolate = object->GetIsolate(); | 4902 Isolate* isolate = object->GetIsolate(); |
| 4917 ASSERT(key->IsUniqueName()); | 4903 ASSERT(key->IsUniqueName()); |
| 4918 | 4904 |
| 4919 if (object->IsJSGlobalProxy()) { | 4905 if (object->IsJSGlobalProxy()) { |
| 4920 Handle<Object> proto(object->GetPrototype(), isolate); | 4906 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4921 if (proto->IsNull()) return; | 4907 if (proto->IsNull()) return; |
| 4922 ASSERT(proto->IsJSGlobalObject()); | 4908 ASSERT(proto->IsJSGlobalObject()); |
| 4923 return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key); | 4909 return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key); |
| 4924 } | 4910 } |
| 4925 | 4911 |
| 4926 MaybeObject* hidden_lookup = | 4912 Object* inline_value = object->GetHiddenPropertiesHashTable(); |
| 4927 object->GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE); | |
| 4928 Object* inline_value = hidden_lookup->ToObjectUnchecked(); | |
| 4929 | 4913 |
| 4930 // We never delete (inline-stored) identity hashes. | 4914 // We never delete (inline-stored) identity hashes. |
| 4931 ASSERT(*key != isolate->heap()->identity_hash_string()); | 4915 ASSERT(*key != *isolate->factory()->identity_hash_string()); |
| 4932 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; | 4916 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; |
| 4933 | 4917 |
| 4934 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 4918 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
| 4935 PutIntoObjectHashTable(hashtable, key, isolate->factory()->the_hole_value()); | 4919 ObjectHashTable::Put(hashtable, key, isolate->factory()->the_hole_value()); |
| 4936 } | 4920 } |
| 4937 | 4921 |
| 4938 | 4922 |
| 4939 bool JSObject::HasHiddenProperties() { | 4923 bool JSObject::HasHiddenProperties() { |
| 4940 return GetPropertyAttributePostInterceptor(this, | 4924 return GetPropertyAttributePostInterceptor(this, |
| 4941 GetHeap()->hidden_string(), | 4925 GetHeap()->hidden_string(), |
| 4942 false) != ABSENT; | 4926 false) != ABSENT; |
| 4943 } | 4927 } |
| 4944 | 4928 |
| 4945 | 4929 |
| 4946 MaybeObject* JSObject::GetHiddenPropertiesHashTable( | 4930 Object* JSObject::GetHiddenPropertiesHashTable() { |
| 4947 InitializeHiddenProperties init_option) { | |
| 4948 ASSERT(!IsJSGlobalProxy()); | 4931 ASSERT(!IsJSGlobalProxy()); |
| 4949 Object* inline_value; | |
| 4950 if (HasFastProperties()) { | 4932 if (HasFastProperties()) { |
| 4951 // If the object has fast properties, check whether the first slot | 4933 // If the object has fast properties, check whether the first slot |
| 4952 // in the descriptor array matches the hidden string. Since the | 4934 // in the descriptor array matches the hidden string. Since the |
| 4953 // 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 |
| 4954 // code zero) it will always occupy the first entry if present. | 4936 // code zero) it will always occupy the first entry if present. |
| 4955 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 4937 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 4956 if (descriptors->number_of_descriptors() > 0) { | 4938 if (descriptors->number_of_descriptors() > 0) { |
| 4957 int sorted_index = descriptors->GetSortedKeyIndex(0); | 4939 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 4958 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 4940 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && |
| 4959 sorted_index < map()->NumberOfOwnDescriptors()) { | 4941 sorted_index < map()->NumberOfOwnDescriptors()) { |
| 4960 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 4942 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 4961 MaybeObject* maybe_value = this->FastPropertyAt( | 4943 ASSERT(descriptors->GetDetails(sorted_index).representation(). |
| 4962 descriptors->GetDetails(sorted_index).representation(), | 4944 IsCompatibleForLoad(Representation::Tagged())); |
| 4945 return this->RawFastPropertyAt( |
| 4963 descriptors->GetFieldIndex(sorted_index)); | 4946 descriptors->GetFieldIndex(sorted_index)); |
| 4964 if (!maybe_value->To(&inline_value)) return maybe_value; | |
| 4965 } else { | 4947 } else { |
| 4966 inline_value = GetHeap()->undefined_value(); | 4948 return GetHeap()->undefined_value(); |
| 4967 } | 4949 } |
| 4968 } else { | 4950 } else { |
| 4969 inline_value = GetHeap()->undefined_value(); | 4951 return GetHeap()->undefined_value(); |
| 4970 } | 4952 } |
| 4971 } else { | 4953 } else { |
| 4972 PropertyAttributes attributes; | 4954 PropertyAttributes attributes; |
| 4973 // 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, |
| 4974 // so we can be sure that GetLocalPropertyPostInterceptor returns a real | 4956 // so we can be sure that GetLocalPropertyPostInterceptor returns a real |
| 4975 // object. | 4957 // object. |
| 4976 inline_value = | 4958 return GetLocalPropertyPostInterceptor(this, |
| 4977 GetLocalPropertyPostInterceptor(this, | 4959 GetHeap()->hidden_string(), |
| 4978 GetHeap()->hidden_string(), | 4960 &attributes)->ToObjectUnchecked(); |
| 4979 &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); |
| 4980 } | 4972 } |
| 4981 | 4973 |
| 4982 if (init_option == ONLY_RETURN_INLINE_VALUE || | 4974 Handle<ObjectHashTable> hashtable = isolate->factory()->NewObjectHashTable( |
| 4983 inline_value->IsHashTable()) { | 4975 kInitialCapacity, |
| 4984 return inline_value; | 4976 USE_CUSTOM_MINIMUM_CAPACITY); |
| 4985 } | |
| 4986 | |
| 4987 ObjectHashTable* hashtable; | |
| 4988 static const int kInitialCapacity = 4; | |
| 4989 MaybeObject* maybe_obj = | |
| 4990 ObjectHashTable::Allocate(GetHeap(), | |
| 4991 kInitialCapacity, | |
| 4992 ObjectHashTable::USE_CUSTOM_MINIMUM_CAPACITY); | |
| 4993 if (!maybe_obj->To<ObjectHashTable>(&hashtable)) return maybe_obj; | |
| 4994 | 4977 |
| 4995 if (inline_value->IsSmi()) { | 4978 if (inline_value->IsSmi()) { |
| 4996 // 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 |
| 4997 // dictionary. Put the identity hash into the new dictionary. | 4980 // dictionary. Put the identity hash into the new dictionary. |
| 4998 MaybeObject* insert_result = | 4981 hashtable = ObjectHashTable::Put(hashtable, |
| 4999 hashtable->Put(GetHeap()->identity_hash_string(), inline_value); | 4982 isolate->factory()->identity_hash_string(), |
| 5000 ObjectHashTable* new_table; | 4983 inline_value); |
| 5001 if (!insert_result->To(&new_table)) return insert_result; | |
| 5002 // We expect no resizing for the first insert. | |
| 5003 ASSERT_EQ(hashtable, new_table); | |
| 5004 } | 4984 } |
| 5005 | 4985 |
| 5006 MaybeObject* store_result = SetLocalPropertyIgnoreAttributesTrampoline( | 4986 JSObject::SetLocalPropertyIgnoreAttributes( |
| 5007 GetHeap()->hidden_string(), | 4987 object, |
| 4988 isolate->factory()->hidden_string(), |
| 5008 hashtable, | 4989 hashtable, |
| 5009 DONT_ENUM, | 4990 DONT_ENUM, |
| 5010 OPTIMAL_REPRESENTATION, | 4991 OPTIMAL_REPRESENTATION, |
| 5011 ALLOW_AS_CONSTANT, | 4992 ALLOW_AS_CONSTANT, |
| 5012 OMIT_EXTENSIBILITY_CHECK); | 4993 OMIT_EXTENSIBILITY_CHECK); |
| 5013 if (store_result->IsFailure()) return store_result; | 4994 |
| 5014 return hashtable; | 4995 return hashtable; |
| 5015 } | 4996 } |
| 5016 | 4997 |
| 5017 | 4998 |
| 5018 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { | 4999 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
| 5019 ASSERT(!IsJSGlobalProxy()); | 5000 Handle<Object> value) { |
| 5001 ASSERT(!object->IsJSGlobalProxy()); |
| 5002 |
| 5003 Isolate* isolate = object->GetIsolate(); |
| 5004 |
| 5020 // 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 |
| 5021 // for hidden properties yet. | 5006 // for hidden properties yet. |
| 5022 ASSERT(HasHiddenProperties() != value->IsSmi()); | 5007 ASSERT(object->HasHiddenProperties() != value->IsSmi()); |
| 5023 if (HasFastProperties()) { | 5008 if (object->HasFastProperties()) { |
| 5024 // If the object has fast properties, check whether the first slot | 5009 // If the object has fast properties, check whether the first slot |
| 5025 // in the descriptor array matches the hidden string. Since the | 5010 // in the descriptor array matches the hidden string. Since the |
| 5026 // 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 |
| 5027 // code zero) it will always occupy the first entry if present. | 5012 // code zero) it will always occupy the first entry if present. |
| 5028 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 5013 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 5029 if (descriptors->number_of_descriptors() > 0) { | 5014 if (descriptors->number_of_descriptors() > 0) { |
| 5030 int sorted_index = descriptors->GetSortedKeyIndex(0); | 5015 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 5031 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 5016 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string() |
| 5032 sorted_index < map()->NumberOfOwnDescriptors()) { | 5017 && sorted_index < object->map()->NumberOfOwnDescriptors()) { |
| 5033 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 5018 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 5034 FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value); | 5019 object->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), |
| 5035 return this; | 5020 *value); |
| 5021 return object; |
| 5036 } | 5022 } |
| 5037 } | 5023 } |
| 5038 } | 5024 } |
| 5039 MaybeObject* store_result = SetLocalPropertyIgnoreAttributesTrampoline( | 5025 |
| 5040 GetHeap()->hidden_string(), | 5026 SetLocalPropertyIgnoreAttributes(object, |
| 5041 value, | 5027 isolate->factory()->hidden_string(), |
| 5042 DONT_ENUM, | 5028 value, |
| 5043 OPTIMAL_REPRESENTATION, | 5029 DONT_ENUM, |
| 5044 ALLOW_AS_CONSTANT, | 5030 OPTIMAL_REPRESENTATION, |
| 5045 OMIT_EXTENSIBILITY_CHECK); | 5031 ALLOW_AS_CONSTANT, |
| 5046 if (store_result->IsFailure()) return store_result; | 5032 OMIT_EXTENSIBILITY_CHECK); |
| 5047 return this; | 5033 return object; |
| 5048 } | 5034 } |
| 5049 | 5035 |
| 5050 | 5036 |
| 5051 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, | 5037 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, |
| 5052 Handle<Name> name, | 5038 Handle<Name> name, |
| 5053 DeleteMode mode) { | 5039 DeleteMode mode) { |
| 5054 // Check local property, ignore interceptor. | 5040 // Check local property, ignore interceptor. |
| 5055 Isolate* isolate = object->GetIsolate(); | 5041 Isolate* isolate = object->GetIsolate(); |
| 5056 LookupResult result(isolate); | 5042 LookupResult result(isolate); |
| 5057 object->LocalLookupRealNamedProperty(*name, &result); | 5043 object->LocalLookupRealNamedProperty(*name, &result); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5190 // Skip interceptor if forcing deletion. | 5176 // Skip interceptor if forcing deletion. |
| 5191 Handle<Object> result; | 5177 Handle<Object> result; |
| 5192 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { | 5178 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { |
| 5193 result = DeleteElementWithInterceptor(object, index); | 5179 result = DeleteElementWithInterceptor(object, index); |
| 5194 } else { | 5180 } else { |
| 5195 result = AccessorDelete(object, index, mode); | 5181 result = AccessorDelete(object, index, mode); |
| 5196 } | 5182 } |
| 5197 | 5183 |
| 5198 if (should_enqueue_change_record && !HasLocalElement(object, index)) { | 5184 if (should_enqueue_change_record && !HasLocalElement(object, index)) { |
| 5199 Handle<String> name = factory->Uint32ToString(index); | 5185 Handle<String> name = factory->Uint32ToString(index); |
| 5200 EnqueueChangeRecord(object, "deleted", name, old_value); | 5186 EnqueueChangeRecord(object, "delete", name, old_value); |
| 5201 } | 5187 } |
| 5202 | 5188 |
| 5203 return result; | 5189 return result; |
| 5204 } | 5190 } |
| 5205 | 5191 |
| 5206 | 5192 |
| 5207 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5193 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
| 5208 Handle<Name> name, | 5194 Handle<Name> name, |
| 5209 DeleteMode mode) { | 5195 DeleteMode mode) { |
| 5210 Isolate* isolate = object->GetIsolate(); | 5196 Isolate* isolate = object->GetIsolate(); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5266 result = DeletePropertyWithInterceptor(object, name); | 5252 result = DeletePropertyWithInterceptor(object, name); |
| 5267 } | 5253 } |
| 5268 } else { | 5254 } else { |
| 5269 // Normalize object if needed. | 5255 // Normalize object if needed. |
| 5270 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5256 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 5271 // Make sure the properties are normalized before removing the entry. | 5257 // Make sure the properties are normalized before removing the entry. |
| 5272 result = DeleteNormalizedProperty(object, name, mode); | 5258 result = DeleteNormalizedProperty(object, name, mode); |
| 5273 } | 5259 } |
| 5274 | 5260 |
| 5275 if (is_observed && !HasLocalProperty(object, name)) { | 5261 if (is_observed && !HasLocalProperty(object, name)) { |
| 5276 EnqueueChangeRecord(object, "deleted", name, old_value); | 5262 EnqueueChangeRecord(object, "delete", name, old_value); |
| 5277 } | 5263 } |
| 5278 | 5264 |
| 5279 return result; | 5265 return result; |
| 5280 } | 5266 } |
| 5281 | 5267 |
| 5282 | 5268 |
| 5283 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, | 5269 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
| 5284 uint32_t index, | 5270 uint32_t index, |
| 5285 DeleteMode mode) { | 5271 DeleteMode mode) { |
| 5286 if (object->IsJSProxy()) { | 5272 if (object->IsJSProxy()) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5428 } | 5414 } |
| 5429 } | 5415 } |
| 5430 | 5416 |
| 5431 // No references to object. | 5417 // No references to object. |
| 5432 return false; | 5418 return false; |
| 5433 } | 5419 } |
| 5434 | 5420 |
| 5435 | 5421 |
| 5436 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { | 5422 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
| 5437 Isolate* isolate = object->GetIsolate(); | 5423 Isolate* isolate = object->GetIsolate(); |
| 5424 |
| 5425 if (!object->map()->is_extensible()) return object; |
| 5426 |
| 5438 if (object->IsAccessCheckNeeded() && | 5427 if (object->IsAccessCheckNeeded() && |
| 5439 !isolate->MayNamedAccess(*object, | 5428 !isolate->MayNamedAccess(*object, |
| 5440 isolate->heap()->undefined_value(), | 5429 isolate->heap()->undefined_value(), |
| 5441 v8::ACCESS_KEYS)) { | 5430 v8::ACCESS_KEYS)) { |
| 5442 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); | 5431 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); |
| 5443 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5432 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5444 return isolate->factory()->false_value(); | 5433 return isolate->factory()->false_value(); |
| 5445 } | 5434 } |
| 5446 | 5435 |
| 5447 if (object->IsJSGlobalProxy()) { | 5436 if (object->IsJSGlobalProxy()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5470 dictionary->set_requires_slow_elements(); | 5459 dictionary->set_requires_slow_elements(); |
| 5471 | 5460 |
| 5472 // Do a map transition, other objects with this map may still | 5461 // Do a map transition, other objects with this map may still |
| 5473 // be extensible. | 5462 // be extensible. |
| 5474 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5463 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5475 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5464 Handle<Map> new_map = Map::Copy(handle(object->map())); |
| 5476 | 5465 |
| 5477 new_map->set_is_extensible(false); | 5466 new_map->set_is_extensible(false); |
| 5478 object->set_map(*new_map); | 5467 object->set_map(*new_map); |
| 5479 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 } |
| 5480 return object; | 5474 return object; |
| 5481 } | 5475 } |
| 5482 | 5476 |
| 5483 | 5477 |
| 5484 template<typename Dictionary> | 5478 template<typename Dictionary> |
| 5485 static void FreezeDictionary(Dictionary* dictionary) { | 5479 static void FreezeDictionary(Dictionary* dictionary) { |
| 5486 int capacity = dictionary->Capacity(); | 5480 int capacity = dictionary->Capacity(); |
| 5487 for (int i = 0; i < capacity; i++) { | 5481 for (int i = 0; i < capacity; i++) { |
| 5488 Object* k = dictionary->KeyAt(i); | 5482 Object* k = dictionary->KeyAt(i); |
| 5489 if (dictionary->IsKey(k)) { | 5483 if (dictionary->IsKey(k)) { |
| 5490 PropertyDetails details = dictionary->DetailsAt(i); | 5484 PropertyDetails details = dictionary->DetailsAt(i); |
| 5491 int attrs = DONT_DELETE; | 5485 int attrs = DONT_DELETE; |
| 5492 // READ_ONLY is an invalid attribute for JS setters/getters. | 5486 // READ_ONLY is an invalid attribute for JS setters/getters. |
| 5493 if (details.type() != CALLBACKS || | 5487 if (details.type() != CALLBACKS || |
| 5494 !dictionary->ValueAt(i)->IsAccessorPair()) { | 5488 !dictionary->ValueAt(i)->IsAccessorPair()) { |
| 5495 attrs |= READ_ONLY; | 5489 attrs |= READ_ONLY; |
| 5496 } | 5490 } |
| 5497 details = details.CopyAddAttributes( | 5491 details = details.CopyAddAttributes( |
| 5498 static_cast<PropertyAttributes>(attrs)); | 5492 static_cast<PropertyAttributes>(attrs)); |
| 5499 dictionary->DetailsAtPut(i, details); | 5493 dictionary->DetailsAtPut(i, details); |
| 5500 } | 5494 } |
| 5501 } | 5495 } |
| 5502 } | 5496 } |
| 5503 | 5497 |
| 5504 | 5498 |
| 5505 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { | 5499 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { |
| 5506 // Freezing non-strict arguments should be handled elsewhere. | 5500 // Freezing non-strict arguments should be handled elsewhere. |
| 5507 ASSERT(!object->HasNonStrictArgumentsElements()); | 5501 ASSERT(!object->HasNonStrictArgumentsElements()); |
| 5502 ASSERT(!object->map()->is_observed()); |
| 5508 | 5503 |
| 5509 if (object->map()->is_frozen()) return object; | 5504 if (object->map()->is_frozen()) return object; |
| 5510 | 5505 |
| 5511 Isolate* isolate = object->GetIsolate(); | 5506 Isolate* isolate = object->GetIsolate(); |
| 5512 if (object->IsAccessCheckNeeded() && | 5507 if (object->IsAccessCheckNeeded() && |
| 5513 !isolate->MayNamedAccess(*object, | 5508 !isolate->MayNamedAccess(*object, |
| 5514 isolate->heap()->undefined_value(), | 5509 isolate->heap()->undefined_value(), |
| 5515 v8::ACCESS_KEYS)) { | 5510 v8::ACCESS_KEYS)) { |
| 5516 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); | 5511 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); |
| 5517 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... |
| 5822 // Deep copy local elements. | 5817 // Deep copy local elements. |
| 5823 // Pixel elements cannot be created using an object literal. | 5818 // Pixel elements cannot be created using an object literal. |
| 5824 ASSERT(!copy->HasExternalArrayElements()); | 5819 ASSERT(!copy->HasExternalArrayElements()); |
| 5825 switch (copy->GetElementsKind()) { | 5820 switch (copy->GetElementsKind()) { |
| 5826 case FAST_SMI_ELEMENTS: | 5821 case FAST_SMI_ELEMENTS: |
| 5827 case FAST_ELEMENTS: | 5822 case FAST_ELEMENTS: |
| 5828 case FAST_HOLEY_SMI_ELEMENTS: | 5823 case FAST_HOLEY_SMI_ELEMENTS: |
| 5829 case FAST_HOLEY_ELEMENTS: { | 5824 case FAST_HOLEY_ELEMENTS: { |
| 5830 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); | 5825 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); |
| 5831 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { | 5826 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { |
| 5832 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 5827 if (copying) { |
| 5828 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
| 5829 } |
| 5833 #ifdef DEBUG | 5830 #ifdef DEBUG |
| 5834 for (int i = 0; i < elements->length(); i++) { | 5831 for (int i = 0; i < elements->length(); i++) { |
| 5835 ASSERT(!elements->get(i)->IsJSObject()); | 5832 ASSERT(!elements->get(i)->IsJSObject()); |
| 5836 } | 5833 } |
| 5837 #endif | 5834 #endif |
| 5838 } else { | 5835 } else { |
| 5839 for (int i = 0; i < elements->length(); i++) { | 5836 for (int i = 0; i < elements->length(); i++) { |
| 5840 Handle<Object> value(elements->get(i), isolate); | 5837 Handle<Object> value(elements->get(i), isolate); |
| 5841 ASSERT(value->IsSmi() || | 5838 ASSERT(value->IsSmi() || |
| 5842 value->IsTheHole() || | 5839 value->IsTheHole() || |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6215 return !AccessorInfo::cast(obj)->prohibits_overwriting(); | 6212 return !AccessorInfo::cast(obj)->prohibits_overwriting(); |
| 6216 } | 6213 } |
| 6217 if (obj->IsAccessorPair()) { | 6214 if (obj->IsAccessorPair()) { |
| 6218 return !AccessorPair::cast(obj)->prohibits_overwriting(); | 6215 return !AccessorPair::cast(obj)->prohibits_overwriting(); |
| 6219 } | 6216 } |
| 6220 } | 6217 } |
| 6221 return true; | 6218 return true; |
| 6222 } | 6219 } |
| 6223 | 6220 |
| 6224 | 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 |
| 6225 void JSObject::SetElementCallback(Handle<JSObject> object, | 6247 void JSObject::SetElementCallback(Handle<JSObject> object, |
| 6226 uint32_t index, | 6248 uint32_t index, |
| 6227 Handle<Object> structure, | 6249 Handle<Object> structure, |
| 6228 PropertyAttributes attributes) { | 6250 PropertyAttributes attributes) { |
| 6229 Heap* heap = object->GetHeap(); | 6251 Heap* heap = object->GetHeap(); |
| 6230 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6252 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| 6231 | 6253 |
| 6232 // Normalize elements to make this operation simple. | 6254 // Normalize elements to make this operation simple. |
| 6255 bool had_dictionary_elements = object->HasDictionaryElements(); |
| 6233 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6256 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 6234 ASSERT(object->HasDictionaryElements() || | 6257 ASSERT(object->HasDictionaryElements() || |
| 6235 object->HasDictionaryArgumentsElements()); | 6258 object->HasDictionaryArgumentsElements()); |
| 6236 | 6259 |
| 6237 // Update the dictionary with the new CALLBACKS property. | 6260 // Update the dictionary with the new CALLBACKS property. |
| 6238 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6261 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| 6239 details); | 6262 details); |
| 6240 dictionary->set_requires_slow_elements(); | 6263 dictionary->set_requires_slow_elements(); |
| 6241 | 6264 |
| 6242 // Update the dictionary backing store on the object. | 6265 // Update the dictionary backing store on the object. |
| 6243 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { | 6266 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { |
| 6244 // Also delete any parameter alias. | 6267 // Also delete any parameter alias. |
| 6245 // | 6268 // |
| 6246 // TODO(kmillikin): when deleting the last parameter alias we could | 6269 // TODO(kmillikin): when deleting the last parameter alias we could |
| 6247 // switch to a direct backing store without the parameter map. This | 6270 // switch to a direct backing store without the parameter map. This |
| 6248 // would allow GC of the context. | 6271 // would allow GC of the context. |
| 6249 FixedArray* parameter_map = FixedArray::cast(object->elements()); | 6272 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 6250 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { | 6273 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { |
| 6251 parameter_map->set(index + 2, heap->the_hole_value()); | 6274 parameter_map->set(index + 2, heap->the_hole_value()); |
| 6252 } | 6275 } |
| 6253 parameter_map->set(1, *dictionary); | 6276 parameter_map->set(1, *dictionary); |
| 6254 } else { | 6277 } else { |
| 6255 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 } |
| 6256 } | 6284 } |
| 6257 } | 6285 } |
| 6258 | 6286 |
| 6259 | 6287 |
| 6260 void JSObject::SetPropertyCallback(Handle<JSObject> object, | 6288 void JSObject::SetPropertyCallback(Handle<JSObject> object, |
| 6261 Handle<Name> name, | 6289 Handle<Name> name, |
| 6262 Handle<Object> structure, | 6290 Handle<Object> structure, |
| 6263 PropertyAttributes attributes) { | 6291 PropertyAttributes attributes) { |
| 6264 // Normalize object to make this operation simple. | 6292 // Normalize object to make this operation simple. |
| 6265 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... |
| 6345 | 6373 |
| 6346 if (is_element) { | 6374 if (is_element) { |
| 6347 DefineElementAccessor( | 6375 DefineElementAccessor( |
| 6348 object, index, getter, setter, attributes, access_control); | 6376 object, index, getter, setter, attributes, access_control); |
| 6349 } else { | 6377 } else { |
| 6350 DefinePropertyAccessor( | 6378 DefinePropertyAccessor( |
| 6351 object, name, getter, setter, attributes, access_control); | 6379 object, name, getter, setter, attributes, access_control); |
| 6352 } | 6380 } |
| 6353 | 6381 |
| 6354 if (is_observed) { | 6382 if (is_observed) { |
| 6355 const char* type = preexists ? "reconfigured" : "new"; | 6383 const char* type = preexists ? "reconfigure" : "add"; |
| 6356 EnqueueChangeRecord(object, type, name, old_value); | 6384 EnqueueChangeRecord(object, type, name, old_value); |
| 6357 } | 6385 } |
| 6358 } | 6386 } |
| 6359 | 6387 |
| 6360 | 6388 |
| 6361 static bool TryAccessorTransition(JSObject* self, | 6389 static bool TryAccessorTransition(JSObject* self, |
| 6362 Map* transitioned_map, | 6390 Map* transitioned_map, |
| 6363 int target_descriptor, | 6391 int target_descriptor, |
| 6364 AccessorComponent component, | 6392 AccessorComponent component, |
| 6365 Object* accessor, | 6393 Object* accessor, |
| (...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7821 return cache; | 7849 return cache; |
| 7822 } | 7850 } |
| 7823 | 7851 |
| 7824 | 7852 |
| 7825 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { | 7853 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 7826 ElementsAccessor* accessor = array->GetElementsAccessor(); | 7854 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 7827 MaybeObject* maybe_result = | 7855 MaybeObject* maybe_result = |
| 7828 accessor->AddElementsToFixedArray(array, array, this); | 7856 accessor->AddElementsToFixedArray(array, array, this); |
| 7829 FixedArray* result; | 7857 FixedArray* result; |
| 7830 if (!maybe_result->To<FixedArray>(&result)) return maybe_result; | 7858 if (!maybe_result->To<FixedArray>(&result)) return maybe_result; |
| 7831 #ifdef DEBUG | 7859 #ifdef ENABLE_SLOW_ASSERTS |
| 7832 if (FLAG_enable_slow_asserts) { | 7860 if (FLAG_enable_slow_asserts) { |
| 7833 for (int i = 0; i < result->length(); i++) { | 7861 for (int i = 0; i < result->length(); i++) { |
| 7834 Object* current = result->get(i); | 7862 Object* current = result->get(i); |
| 7835 ASSERT(current->IsNumber() || current->IsName()); | 7863 ASSERT(current->IsNumber() || current->IsName()); |
| 7836 } | 7864 } |
| 7837 } | 7865 } |
| 7838 #endif | 7866 #endif |
| 7839 return result; | 7867 return result; |
| 7840 } | 7868 } |
| 7841 | 7869 |
| 7842 | 7870 |
| 7843 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { | 7871 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { |
| 7844 ElementsAccessor* accessor = ElementsAccessor::ForArray(other); | 7872 ElementsAccessor* accessor = ElementsAccessor::ForArray(other); |
| 7845 MaybeObject* maybe_result = | 7873 MaybeObject* maybe_result = |
| 7846 accessor->AddElementsToFixedArray(NULL, NULL, this, other); | 7874 accessor->AddElementsToFixedArray(NULL, NULL, this, other); |
| 7847 FixedArray* result; | 7875 FixedArray* result; |
| 7848 if (!maybe_result->To(&result)) return maybe_result; | 7876 if (!maybe_result->To(&result)) return maybe_result; |
| 7849 #ifdef DEBUG | 7877 #ifdef ENABLE_SLOW_ASSERTS |
| 7850 if (FLAG_enable_slow_asserts) { | 7878 if (FLAG_enable_slow_asserts) { |
| 7851 for (int i = 0; i < result->length(); i++) { | 7879 for (int i = 0; i < result->length(); i++) { |
| 7852 Object* current = result->get(i); | 7880 Object* current = result->get(i); |
| 7853 ASSERT(current->IsNumber() || current->IsName()); | 7881 ASSERT(current->IsNumber() || current->IsName()); |
| 7854 } | 7882 } |
| 7855 } | 7883 } |
| 7856 #endif | 7884 #endif |
| 7857 return result; | 7885 return result; |
| 7858 } | 7886 } |
| 7859 | 7887 |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8304 } | 8332 } |
| 8305 | 8333 |
| 8306 | 8334 |
| 8307 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 8335 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
| 8308 RobustnessFlag robust_flag, | 8336 RobustnessFlag robust_flag, |
| 8309 int* length_return) { | 8337 int* length_return) { |
| 8310 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); | 8338 return ToCString(allow_nulls, robust_flag, 0, -1, length_return); |
| 8311 } | 8339 } |
| 8312 | 8340 |
| 8313 | 8341 |
| 8314 const uc16* String::GetTwoByteData() { | |
| 8315 return GetTwoByteData(0); | |
| 8316 } | |
| 8317 | |
| 8318 | |
| 8319 const uc16* String::GetTwoByteData(unsigned start) { | 8342 const uc16* String::GetTwoByteData(unsigned start) { |
| 8320 ASSERT(!IsOneByteRepresentationUnderneath()); | 8343 ASSERT(!IsOneByteRepresentationUnderneath()); |
| 8321 switch (StringShape(this).representation_tag()) { | 8344 switch (StringShape(this).representation_tag()) { |
| 8322 case kSeqStringTag: | 8345 case kSeqStringTag: |
| 8323 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); | 8346 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); |
| 8324 case kExternalStringTag: | 8347 case kExternalStringTag: |
| 8325 return ExternalTwoByteString::cast(this)-> | 8348 return ExternalTwoByteString::cast(this)-> |
| 8326 ExternalTwoByteStringGetData(start); | 8349 ExternalTwoByteStringGetData(start); |
| 8327 case kSlicedStringTag: { | 8350 case kSlicedStringTag: { |
| 8328 SlicedString* slice = SlicedString::cast(this); | 8351 SlicedString* slice = SlicedString::cast(this); |
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8894 | 8917 |
| 8895 bool String::SlowEquals(String* other) { | 8918 bool String::SlowEquals(String* other) { |
| 8896 // Fast check: negative check with lengths. | 8919 // Fast check: negative check with lengths. |
| 8897 int len = length(); | 8920 int len = length(); |
| 8898 if (len != other->length()) return false; | 8921 if (len != other->length()) return false; |
| 8899 if (len == 0) return true; | 8922 if (len == 0) return true; |
| 8900 | 8923 |
| 8901 // Fast check: if hash code is computed for both strings | 8924 // Fast check: if hash code is computed for both strings |
| 8902 // a fast negative check can be performed. | 8925 // a fast negative check can be performed. |
| 8903 if (HasHashCode() && other->HasHashCode()) { | 8926 if (HasHashCode() && other->HasHashCode()) { |
| 8904 #ifdef DEBUG | 8927 #ifdef ENABLE_SLOW_ASSERTS |
| 8905 if (FLAG_enable_slow_asserts) { | 8928 if (FLAG_enable_slow_asserts) { |
| 8906 if (Hash() != other->Hash()) { | 8929 if (Hash() != other->Hash()) { |
| 8907 bool found_difference = false; | 8930 bool found_difference = false; |
| 8908 for (int i = 0; i < len; i++) { | 8931 for (int i = 0; i < len; i++) { |
| 8909 if (Get(i) != other->Get(i)) { | 8932 if (Get(i) != other->Get(i)) { |
| 8910 found_difference = true; | 8933 found_difference = true; |
| 8911 break; | 8934 break; |
| 8912 } | 8935 } |
| 8913 } | 8936 } |
| 8914 ASSERT(found_difference); | 8937 ASSERT(found_difference); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9149 | 9172 |
| 9150 Address start_of_string = string->address(); | 9173 Address start_of_string = string->address(); |
| 9151 ASSERT_OBJECT_ALIGNED(start_of_string); | 9174 ASSERT_OBJECT_ALIGNED(start_of_string); |
| 9152 ASSERT_OBJECT_ALIGNED(start_of_string + new_size); | 9175 ASSERT_OBJECT_ALIGNED(start_of_string + new_size); |
| 9153 | 9176 |
| 9154 Heap* heap = string->GetHeap(); | 9177 Heap* heap = string->GetHeap(); |
| 9155 NewSpace* newspace = heap->new_space(); | 9178 NewSpace* newspace = heap->new_space(); |
| 9156 if (newspace->Contains(start_of_string) && | 9179 if (newspace->Contains(start_of_string) && |
| 9157 newspace->top() == start_of_string + old_size) { | 9180 newspace->top() == start_of_string + old_size) { |
| 9158 // Last allocated object in new space. Simply lower allocation top. | 9181 // Last allocated object in new space. Simply lower allocation top. |
| 9159 *(newspace->allocation_top_address()) = start_of_string + new_size; | 9182 newspace->set_top(start_of_string + new_size); |
| 9160 } else { | 9183 } else { |
| 9161 // Sizes are pointer size aligned, so that we can use filler objects | 9184 // Sizes are pointer size aligned, so that we can use filler objects |
| 9162 // that are a multiple of pointer size. | 9185 // that are a multiple of pointer size. |
| 9163 heap->CreateFillerObjectAt(start_of_string + new_size, delta); | 9186 heap->CreateFillerObjectAt(start_of_string + new_size, delta); |
| 9164 } | 9187 } |
| 9165 if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { | 9188 if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) { |
| 9166 MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); | 9189 MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta); |
| 9167 } | 9190 } |
| 9168 | 9191 |
| 9169 | 9192 |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9553 FixedArray* literals) { | 9576 FixedArray* literals) { |
| 9554 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 9577 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); |
| 9555 ASSERT(native_context->IsNativeContext()); | 9578 ASSERT(native_context->IsNativeContext()); |
| 9556 STATIC_ASSERT(kEntryLength == 3); | 9579 STATIC_ASSERT(kEntryLength == 3); |
| 9557 Heap* heap = GetHeap(); | 9580 Heap* heap = GetHeap(); |
| 9558 FixedArray* new_code_map; | 9581 FixedArray* new_code_map; |
| 9559 Object* value = optimized_code_map(); | 9582 Object* value = optimized_code_map(); |
| 9560 if (value->IsSmi()) { | 9583 if (value->IsSmi()) { |
| 9561 // No optimized code map. | 9584 // No optimized code map. |
| 9562 ASSERT_EQ(0, Smi::cast(value)->value()); | 9585 ASSERT_EQ(0, Smi::cast(value)->value()); |
| 9563 // Crate 3 entries per context {context, code, literals}. | 9586 // Create 3 entries per context {context, code, literals}. |
| 9564 MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength); | 9587 MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength); |
| 9565 if (!maybe->To(&new_code_map)) return maybe; | 9588 if (!maybe->To(&new_code_map)) return maybe; |
| 9566 new_code_map->set(kEntriesStart + 0, native_context); | 9589 new_code_map->set(kEntriesStart + 0, native_context); |
| 9567 new_code_map->set(kEntriesStart + 1, code); | 9590 new_code_map->set(kEntriesStart + 1, code); |
| 9568 new_code_map->set(kEntriesStart + 2, literals); | 9591 new_code_map->set(kEntriesStart + 2, literals); |
| 9569 } else { | 9592 } else { |
| 9570 // Copy old map and append one new entry. | 9593 // Copy old map and append one new entry. |
| 9571 FixedArray* old_code_map = FixedArray::cast(value); | 9594 FixedArray* old_code_map = FixedArray::cast(value); |
| 9572 ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context)); | 9595 ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context)); |
| 9573 int old_length = old_code_map->length(); | 9596 int old_length = old_code_map->length(); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9712 return CompileLazyHelper(&info, flag); | 9735 return CompileLazyHelper(&info, flag); |
| 9713 } | 9736 } |
| 9714 | 9737 |
| 9715 | 9738 |
| 9716 bool JSFunction::EnsureCompiled(Handle<JSFunction> function, | 9739 bool JSFunction::EnsureCompiled(Handle<JSFunction> function, |
| 9717 ClearExceptionFlag flag) { | 9740 ClearExceptionFlag flag) { |
| 9718 return function->is_compiled() || CompileLazy(function, flag); | 9741 return function->is_compiled() || CompileLazy(function, flag); |
| 9719 } | 9742 } |
| 9720 | 9743 |
| 9721 | 9744 |
| 9722 bool JSFunction::IsInlineable() { | |
| 9723 if (IsBuiltin()) return false; | |
| 9724 SharedFunctionInfo* shared_info = shared(); | |
| 9725 // Check that the function has a script associated with it. | |
| 9726 if (!shared_info->script()->IsScript()) return false; | |
| 9727 if (shared_info->optimization_disabled()) return false; | |
| 9728 Code* code = shared_info->code(); | |
| 9729 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | |
| 9730 // If we never ran this (unlikely) then lets try to optimize it. | |
| 9731 if (code->kind() != Code::FUNCTION) return true; | |
| 9732 return code->optimizable(); | |
| 9733 } | |
| 9734 | |
| 9735 | |
| 9736 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { | 9745 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { |
| 9737 if (object->IsGlobalObject()) return; | 9746 if (object->IsGlobalObject()) return; |
| 9738 | 9747 |
| 9739 // Make sure prototypes are fast objects and their maps have the bit set | 9748 // Make sure prototypes are fast objects and their maps have the bit set |
| 9740 // so they remain fast. | 9749 // so they remain fast. |
| 9741 if (!object->HasFastProperties()) { | 9750 if (!object->HasFastProperties()) { |
| 9742 TransformToFastProperties(object, 0); | 9751 TransformToFastProperties(object, 0); |
| 9743 } | 9752 } |
| 9744 } | 9753 } |
| 9745 | 9754 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9869 | 9878 |
| 9870 ASSERT(map() == (shared()->is_classic_mode() | 9879 ASSERT(map() == (shared()->is_classic_mode() |
| 9871 ? native_context->function_map() | 9880 ? native_context->function_map() |
| 9872 : native_context->strict_mode_function_map())); | 9881 : native_context->strict_mode_function_map())); |
| 9873 | 9882 |
| 9874 set_map(no_prototype_map); | 9883 set_map(no_prototype_map); |
| 9875 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); | 9884 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); |
| 9876 } | 9885 } |
| 9877 | 9886 |
| 9878 | 9887 |
| 9888 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { |
| 9889 if (function->has_initial_map()) return; |
| 9890 Isolate* isolate = function->GetIsolate(); |
| 9891 |
| 9892 // First create a new map with the size and number of in-object properties |
| 9893 // suggested by the function. |
| 9894 InstanceType instance_type; |
| 9895 int instance_size; |
| 9896 int in_object_properties; |
| 9897 if (function->shared()->is_generator()) { |
| 9898 instance_type = JS_GENERATOR_OBJECT_TYPE; |
| 9899 instance_size = JSGeneratorObject::kSize; |
| 9900 in_object_properties = 0; |
| 9901 } else { |
| 9902 instance_type = JS_OBJECT_TYPE; |
| 9903 instance_size = function->shared()->CalculateInstanceSize(); |
| 9904 in_object_properties = function->shared()->CalculateInObjectProperties(); |
| 9905 } |
| 9906 Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size); |
| 9907 |
| 9908 // Fetch or allocate prototype. |
| 9909 Handle<Object> prototype; |
| 9910 if (function->has_instance_prototype()) { |
| 9911 prototype = handle(function->instance_prototype(), isolate); |
| 9912 } else { |
| 9913 prototype = isolate->factory()->NewFunctionPrototype(function); |
| 9914 } |
| 9915 map->set_inobject_properties(in_object_properties); |
| 9916 map->set_unused_property_fields(in_object_properties); |
| 9917 map->set_prototype(*prototype); |
| 9918 ASSERT(map->has_fast_object_elements()); |
| 9919 |
| 9920 if (!function->shared()->is_generator()) { |
| 9921 function->shared()->StartInobjectSlackTracking(*map); |
| 9922 } |
| 9923 |
| 9924 // Finally link initial map and constructor function. |
| 9925 function->set_initial_map(*map); |
| 9926 map->set_constructor(*function); |
| 9927 } |
| 9928 |
| 9929 |
| 9879 void JSFunction::SetInstanceClassName(String* name) { | 9930 void JSFunction::SetInstanceClassName(String* name) { |
| 9880 shared()->set_instance_class_name(name); | 9931 shared()->set_instance_class_name(name); |
| 9881 } | 9932 } |
| 9882 | 9933 |
| 9883 | 9934 |
| 9884 void JSFunction::PrintName(FILE* out) { | 9935 void JSFunction::PrintName(FILE* out) { |
| 9885 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); | 9936 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); |
| 9886 PrintF(out, "%s", *name); | 9937 PrintF(out, "%s", *name); |
| 9887 } | 9938 } |
| 9888 | 9939 |
| 9889 | 9940 |
| 9890 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) { | 9941 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) { |
| 9891 return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex)); | 9942 return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex)); |
| 9892 } | 9943 } |
| 9893 | 9944 |
| 9894 | 9945 |
| 9895 // The filter is a pattern that matches function names in this way: | 9946 // The filter is a pattern that matches function names in this way: |
| 9896 // "*" all; the default | 9947 // "*" all; the default |
| 9897 // "-" all but the top-level function | 9948 // "-" all but the top-level function |
| 9898 // "-name" all but the function "name" | 9949 // "-name" all but the function "name" |
| 9899 // "" only the top-level function | 9950 // "" only the top-level function |
| 9900 // "name" only the function "name" | 9951 // "name" only the function "name" |
| 9901 // "name*" only functions starting with "name" | 9952 // "name*" only functions starting with "name" |
| 9902 bool JSFunction::PassesFilter(const char* raw_filter) { | 9953 bool JSFunction::PassesFilter(const char* raw_filter) { |
| 9903 if (*raw_filter == '*') return true; | 9954 if (*raw_filter == '*') return true; |
| 9904 String* name = shared()->DebugName(); | 9955 String* name = shared()->DebugName(); |
| 9905 Vector<const char> filter = CStrVector(raw_filter); | 9956 Vector<const char> filter = CStrVector(raw_filter); |
| 9906 if (filter.length() == 0) return name->length() == 0; | 9957 if (filter.length() == 0) return name->length() == 0; |
| 9907 if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true; | 9958 if (filter[0] == '-') { |
| 9908 if (filter[0] == '-' && | 9959 if (filter.length() == 1) { |
| 9909 !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { | 9960 return (name->length() != 0); |
| 9961 } else if (!name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { |
| 9962 return true; |
| 9963 } |
| 9964 } else if (name->IsUtf8EqualTo(filter)) { |
| 9910 return true; | 9965 return true; |
| 9911 } | 9966 } |
| 9912 if (filter[filter.length() - 1] == '*' && | 9967 if (filter[filter.length() - 1] == '*' && |
| 9913 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { | 9968 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { |
| 9914 return true; | 9969 return true; |
| 9915 } | 9970 } |
| 9916 return false; | 9971 return false; |
| 9917 } | 9972 } |
| 9918 | 9973 |
| 9919 | 9974 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 9948 | 10003 |
| 9949 | 10004 |
| 9950 Handle<Object> SharedFunctionInfo::GetSourceCode() { | 10005 Handle<Object> SharedFunctionInfo::GetSourceCode() { |
| 9951 if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value(); | 10006 if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value(); |
| 9952 Handle<String> source(String::cast(Script::cast(script())->source())); | 10007 Handle<String> source(String::cast(Script::cast(script())->source())); |
| 9953 return GetIsolate()->factory()->NewSubString( | 10008 return GetIsolate()->factory()->NewSubString( |
| 9954 source, start_position(), end_position()); | 10009 source, start_position(), end_position()); |
| 9955 } | 10010 } |
| 9956 | 10011 |
| 9957 | 10012 |
| 10013 bool SharedFunctionInfo::IsInlineable() { |
| 10014 // Check that the function has a script associated with it. |
| 10015 if (!script()->IsScript()) return false; |
| 10016 if (optimization_disabled()) return false; |
| 10017 // If we never ran this (unlikely) then lets try to optimize it. |
| 10018 if (code()->kind() != Code::FUNCTION) return true; |
| 10019 return code()->optimizable(); |
| 10020 } |
| 10021 |
| 10022 |
| 9958 int SharedFunctionInfo::SourceSize() { | 10023 int SharedFunctionInfo::SourceSize() { |
| 9959 return end_position() - start_position(); | 10024 return end_position() - start_position(); |
| 9960 } | 10025 } |
| 9961 | 10026 |
| 9962 | 10027 |
| 9963 int SharedFunctionInfo::CalculateInstanceSize() { | 10028 int SharedFunctionInfo::CalculateInstanceSize() { |
| 9964 int instance_size = | 10029 int instance_size = |
| 9965 JSObject::kHeaderSize + | 10030 JSObject::kHeaderSize + |
| 9966 expected_nof_properties() * kPointerSize; | 10031 expected_nof_properties() * kPointerSize; |
| 9967 if (instance_size > JSObject::kMaxInstanceSize) { | 10032 if (instance_size > JSObject::kMaxInstanceSize) { |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10298 rinfo->IsPatchedDebugBreakSlotSequence())); | 10363 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 10299 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 10364 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 10300 Object* old_target = target; | 10365 Object* old_target = target; |
| 10301 VisitPointer(&target); | 10366 VisitPointer(&target); |
| 10302 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 10367 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 10303 } | 10368 } |
| 10304 | 10369 |
| 10305 | 10370 |
| 10306 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { | 10371 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { |
| 10307 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 10372 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 10308 VisitPointer(rinfo->target_object_address()); | 10373 Object* p = rinfo->target_object(); |
| 10374 VisitPointer(&p); |
| 10309 } | 10375 } |
| 10310 | 10376 |
| 10311 | 10377 |
| 10312 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { | 10378 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { |
| 10313 Address* p = rinfo->target_reference_address(); | 10379 Address p = rinfo->target_reference(); |
| 10314 VisitExternalReference(p); | 10380 VisitExternalReference(&p); |
| 10315 } | 10381 } |
| 10316 | 10382 |
| 10317 | 10383 |
| 10318 void Code::InvalidateRelocation() { | 10384 void Code::InvalidateRelocation() { |
| 10319 set_relocation_info(GetHeap()->empty_byte_array()); | 10385 set_relocation_info(GetHeap()->empty_byte_array()); |
| 10320 } | 10386 } |
| 10321 | 10387 |
| 10322 | 10388 |
| 10323 void Code::Relocate(intptr_t delta) { | 10389 void Code::Relocate(intptr_t delta) { |
| 10324 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 10390 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10461 | 10527 |
| 10462 Map* Code::FindFirstMap() { | 10528 Map* Code::FindFirstMap() { |
| 10463 Object* result = FindNthObject(1, GetHeap()->meta_map()); | 10529 Object* result = FindNthObject(1, GetHeap()->meta_map()); |
| 10464 return (result != NULL) ? Map::cast(result) : NULL; | 10530 return (result != NULL) ? Map::cast(result) : NULL; |
| 10465 } | 10531 } |
| 10466 | 10532 |
| 10467 | 10533 |
| 10468 void Code::ReplaceNthObject(int n, | 10534 void Code::ReplaceNthObject(int n, |
| 10469 Map* match_map, | 10535 Map* match_map, |
| 10470 Object* replace_with) { | 10536 Object* replace_with) { |
| 10471 ASSERT(is_inline_cache_stub()); | 10537 ASSERT(is_inline_cache_stub() || is_handler()); |
| 10472 DisallowHeapAllocation no_allocation; | 10538 DisallowHeapAllocation no_allocation; |
| 10473 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 10539 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 10474 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10540 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10475 RelocInfo* info = it.rinfo(); | 10541 RelocInfo* info = it.rinfo(); |
| 10476 Object* object = info->target_object(); | 10542 Object* object = info->target_object(); |
| 10477 if (object->IsHeapObject()) { | 10543 if (object->IsHeapObject()) { |
| 10478 if (HeapObject::cast(object)->map() == match_map) { | 10544 if (HeapObject::cast(object)->map() == match_map) { |
| 10479 if (--n == 0) { | 10545 if (--n == 0) { |
| 10480 info->set_target_object(replace_with); | 10546 info->set_target_object(replace_with); |
| 10481 return; | 10547 return; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10558 if (--n == 0) { | 10624 if (--n == 0) { |
| 10559 info->set_target_cell(replace_with); | 10625 info->set_target_cell(replace_with); |
| 10560 return; | 10626 return; |
| 10561 } | 10627 } |
| 10562 } | 10628 } |
| 10563 UNREACHABLE(); | 10629 UNREACHABLE(); |
| 10564 } | 10630 } |
| 10565 | 10631 |
| 10566 | 10632 |
| 10567 void Code::ClearInlineCaches() { | 10633 void Code::ClearInlineCaches() { |
| 10634 ClearInlineCaches(NULL); |
| 10635 } |
| 10636 |
| 10637 |
| 10638 void Code::ClearInlineCaches(Code::Kind kind) { |
| 10639 ClearInlineCaches(&kind); |
| 10640 } |
| 10641 |
| 10642 |
| 10643 void Code::ClearInlineCaches(Code::Kind* kind) { |
| 10568 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | 10644 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 10569 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | | 10645 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
| 10570 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | | 10646 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | |
| 10571 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); | 10647 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); |
| 10572 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10648 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10573 RelocInfo* info = it.rinfo(); | 10649 RelocInfo* info = it.rinfo(); |
| 10574 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); | 10650 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); |
| 10575 if (target->is_inline_cache_stub()) { | 10651 if (target->is_inline_cache_stub()) { |
| 10576 IC::Clear(this->GetIsolate(), info->pc()); | 10652 if (kind == NULL || *kind == target->kind()) { |
| 10653 IC::Clear(this->GetIsolate(), info->pc()); |
| 10654 } |
| 10577 } | 10655 } |
| 10578 } | 10656 } |
| 10579 } | 10657 } |
| 10580 | 10658 |
| 10581 | 10659 |
| 10582 void Code::ClearTypeFeedbackCells(Heap* heap) { | 10660 void Code::ClearTypeFeedbackCells(Heap* heap) { |
| 10583 if (kind() != FUNCTION) return; | 10661 if (kind() != FUNCTION) return; |
| 10584 Object* raw_info = type_feedback_info(); | 10662 Object* raw_info = type_feedback_info(); |
| 10585 if (raw_info->IsTypeFeedbackInfo()) { | 10663 if (raw_info->IsTypeFeedbackInfo()) { |
| 10586 TypeFeedbackCells* type_feedback_cells = | 10664 TypeFeedbackCells* type_feedback_cells = |
| (...skipping 25 matching lines...) Expand all Loading... |
| 10612 PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY); | 10690 PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY); |
| 10613 } | 10691 } |
| 10614 | 10692 |
| 10615 | 10693 |
| 10616 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) { | 10694 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) { |
| 10617 PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge, | 10695 PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge, |
| 10618 NO_MARKING_PARITY); | 10696 NO_MARKING_PARITY); |
| 10619 } | 10697 } |
| 10620 | 10698 |
| 10621 | 10699 |
| 10700 static Code::Age EffectiveAge(Code::Age age) { |
| 10701 if (age == Code::kNotExecutedCodeAge) { |
| 10702 // Treat that's never been executed as old immediately. |
| 10703 age = Code::kIsOldCodeAge; |
| 10704 } else if (age == Code::kExecutedOnceCodeAge) { |
| 10705 // Pre-age code that has only been executed once. |
| 10706 age = Code::kPreAgedCodeAge; |
| 10707 } |
| 10708 return age; |
| 10709 } |
| 10710 |
| 10711 |
| 10622 void Code::MakeOlder(MarkingParity current_parity) { | 10712 void Code::MakeOlder(MarkingParity current_parity) { |
| 10623 byte* sequence = FindCodeAgeSequence(); | 10713 byte* sequence = FindCodeAgeSequence(); |
| 10624 if (sequence != NULL) { | 10714 if (sequence != NULL) { |
| 10625 Age age; | 10715 Age age; |
| 10626 MarkingParity code_parity; | 10716 MarkingParity code_parity; |
| 10627 GetCodeAgeAndParity(sequence, &age, &code_parity); | 10717 GetCodeAgeAndParity(sequence, &age, &code_parity); |
| 10718 age = EffectiveAge(age); |
| 10628 if (age != kLastCodeAge && code_parity != current_parity) { | 10719 if (age != kLastCodeAge && code_parity != current_parity) { |
| 10629 PatchPlatformCodeAge(GetIsolate(), | 10720 PatchPlatformCodeAge(GetIsolate(), |
| 10630 sequence, | 10721 sequence, |
| 10631 static_cast<Age>(age + 1), | 10722 static_cast<Age>(age + 1), |
| 10632 current_parity); | 10723 current_parity); |
| 10633 } | 10724 } |
| 10634 } | 10725 } |
| 10635 } | 10726 } |
| 10636 | 10727 |
| 10637 | 10728 |
| 10638 bool Code::IsOld() { | 10729 bool Code::IsOld() { |
| 10639 Age age = GetAge(); | 10730 return GetAge() >= kIsOldCodeAge; |
| 10640 return age >= kIsOldCodeAge; | |
| 10641 } | 10731 } |
| 10642 | 10732 |
| 10643 | 10733 |
| 10644 byte* Code::FindCodeAgeSequence() { | 10734 byte* Code::FindCodeAgeSequence() { |
| 10645 return FLAG_age_code && | 10735 return FLAG_age_code && |
| 10646 prologue_offset() != Code::kPrologueOffsetNotSet && | 10736 prologue_offset() != Code::kPrologueOffsetNotSet && |
| 10647 (kind() == OPTIMIZED_FUNCTION || | 10737 (kind() == OPTIMIZED_FUNCTION || |
| 10648 (kind() == FUNCTION && !has_debug_break_slots())) | 10738 (kind() == FUNCTION && !has_debug_break_slots())) |
| 10649 ? instruction_start() + prologue_offset() | 10739 ? instruction_start() + prologue_offset() |
| 10650 : NULL; | 10740 : NULL; |
| 10651 } | 10741 } |
| 10652 | 10742 |
| 10653 | 10743 |
| 10654 Code::Age Code::GetAge() { | 10744 Code::Age Code::GetAge() { |
| 10745 return EffectiveAge(GetRawAge()); |
| 10746 } |
| 10747 |
| 10748 |
| 10749 Code::Age Code::GetRawAge() { |
| 10655 byte* sequence = FindCodeAgeSequence(); | 10750 byte* sequence = FindCodeAgeSequence(); |
| 10656 if (sequence == NULL) { | 10751 if (sequence == NULL) { |
| 10657 return Code::kNoAgeCodeAge; | 10752 return kNoAgeCodeAge; |
| 10658 } | 10753 } |
| 10659 Age age; | 10754 Age age; |
| 10660 MarkingParity parity; | 10755 MarkingParity parity; |
| 10661 GetCodeAgeAndParity(sequence, &age, &parity); | 10756 GetCodeAgeAndParity(sequence, &age, &parity); |
| 10662 return age; | 10757 return age; |
| 10663 } | 10758 } |
| 10664 | 10759 |
| 10665 | 10760 |
| 10666 void Code::GetCodeAgeAndParity(Code* code, Age* age, | 10761 void Code::GetCodeAgeAndParity(Code* code, Age* age, |
| 10667 MarkingParity* parity) { | 10762 MarkingParity* parity) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 10678 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ | 10773 stub = *builtins->Make##AGE##CodeYoungAgainOddMarking(); \ |
| 10679 if (code == stub) { \ | 10774 if (code == stub) { \ |
| 10680 *age = k##AGE##CodeAge; \ | 10775 *age = k##AGE##CodeAge; \ |
| 10681 *parity = ODD_MARKING_PARITY; \ | 10776 *parity = ODD_MARKING_PARITY; \ |
| 10682 return; \ | 10777 return; \ |
| 10683 } | 10778 } |
| 10684 CODE_AGE_LIST(HANDLE_CODE_AGE) | 10779 CODE_AGE_LIST(HANDLE_CODE_AGE) |
| 10685 #undef HANDLE_CODE_AGE | 10780 #undef HANDLE_CODE_AGE |
| 10686 stub = *builtins->MarkCodeAsExecutedOnce(); | 10781 stub = *builtins->MarkCodeAsExecutedOnce(); |
| 10687 if (code == stub) { | 10782 if (code == stub) { |
| 10688 // Treat that's never been executed as old immediatly. | 10783 *age = kNotExecutedCodeAge; |
| 10689 *age = kIsOldCodeAge; | |
| 10690 *parity = NO_MARKING_PARITY; | 10784 *parity = NO_MARKING_PARITY; |
| 10691 return; | 10785 return; |
| 10692 } | 10786 } |
| 10693 stub = *builtins->MarkCodeAsExecutedTwice(); | 10787 stub = *builtins->MarkCodeAsExecutedTwice(); |
| 10694 if (code == stub) { | 10788 if (code == stub) { |
| 10695 // Pre-age code that has only been executed once. | 10789 *age = kExecutedOnceCodeAge; |
| 10696 *age = kPreAgedCodeAge; | |
| 10697 *parity = NO_MARKING_PARITY; | 10790 *parity = NO_MARKING_PARITY; |
| 10698 return; | 10791 return; |
| 10699 } | 10792 } |
| 10700 UNREACHABLE(); | 10793 UNREACHABLE(); |
| 10701 } | 10794 } |
| 10702 | 10795 |
| 10703 | 10796 |
| 10704 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { | 10797 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) { |
| 10705 Builtins* builtins = isolate->builtins(); | 10798 Builtins* builtins = isolate->builtins(); |
| 10706 switch (age) { | 10799 switch (age) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 10722 return *builtins->MarkCodeAsExecutedTwice(); | 10815 return *builtins->MarkCodeAsExecutedTwice(); |
| 10723 } | 10816 } |
| 10724 default: | 10817 default: |
| 10725 UNREACHABLE(); | 10818 UNREACHABLE(); |
| 10726 break; | 10819 break; |
| 10727 } | 10820 } |
| 10728 return NULL; | 10821 return NULL; |
| 10729 } | 10822 } |
| 10730 | 10823 |
| 10731 | 10824 |
| 10732 void Code::PrintDeoptLocation(int bailout_id) { | 10825 void Code::PrintDeoptLocation(FILE* out, int bailout_id) { |
| 10733 const char* last_comment = NULL; | 10826 const char* last_comment = NULL; |
| 10734 int mask = RelocInfo::ModeMask(RelocInfo::COMMENT) | 10827 int mask = RelocInfo::ModeMask(RelocInfo::COMMENT) |
| 10735 | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 10828 | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
| 10736 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10829 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10737 RelocInfo* info = it.rinfo(); | 10830 RelocInfo* info = it.rinfo(); |
| 10738 if (info->rmode() == RelocInfo::COMMENT) { | 10831 if (info->rmode() == RelocInfo::COMMENT) { |
| 10739 last_comment = reinterpret_cast<const char*>(info->data()); | 10832 last_comment = reinterpret_cast<const char*>(info->data()); |
| 10740 } else if (last_comment != NULL) { | 10833 } else if (last_comment != NULL) { |
| 10741 if ((bailout_id == Deoptimizer::GetDeoptimizationId( | 10834 if ((bailout_id == Deoptimizer::GetDeoptimizationId( |
| 10742 GetIsolate(), info->target_address(), Deoptimizer::EAGER)) || | 10835 GetIsolate(), info->target_address(), Deoptimizer::EAGER)) || |
| 10743 (bailout_id == Deoptimizer::GetDeoptimizationId( | 10836 (bailout_id == Deoptimizer::GetDeoptimizationId( |
| 10744 GetIsolate(), info->target_address(), Deoptimizer::SOFT))) { | 10837 GetIsolate(), info->target_address(), Deoptimizer::SOFT))) { |
| 10745 CHECK(RelocInfo::IsRuntimeEntry(info->rmode())); | 10838 CHECK(RelocInfo::IsRuntimeEntry(info->rmode())); |
| 10746 PrintF(" %s\n", last_comment); | 10839 PrintF(out, " %s\n", last_comment); |
| 10747 return; | 10840 return; |
| 10748 } | 10841 } |
| 10749 } | 10842 } |
| 10750 } | 10843 } |
| 10751 } | 10844 } |
| 10752 | 10845 |
| 10753 | 10846 |
| 10754 bool Code::CanDeoptAt(Address pc) { | 10847 bool Code::CanDeoptAt(Address pc) { |
| 10755 DeoptimizationInputData* deopt_data = | 10848 DeoptimizationInputData* deopt_data = |
| 10756 DeoptimizationInputData::cast(deoptimization_data()); | 10849 DeoptimizationInputData::cast(deoptimization_data()); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10938 } | 11031 } |
| 10939 } | 11032 } |
| 10940 } | 11033 } |
| 10941 | 11034 |
| 10942 | 11035 |
| 10943 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) { | 11036 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) { |
| 10944 PrintF(out, "Deoptimization Output Data (deopt points = %d)\n", | 11037 PrintF(out, "Deoptimization Output Data (deopt points = %d)\n", |
| 10945 this->DeoptPoints()); | 11038 this->DeoptPoints()); |
| 10946 if (this->DeoptPoints() == 0) return; | 11039 if (this->DeoptPoints() == 0) return; |
| 10947 | 11040 |
| 10948 PrintF("%6s %8s %s\n", "ast id", "pc", "state"); | 11041 PrintF(out, "%6s %8s %s\n", "ast id", "pc", "state"); |
| 10949 for (int i = 0; i < this->DeoptPoints(); i++) { | 11042 for (int i = 0; i < this->DeoptPoints(); i++) { |
| 10950 int pc_and_state = this->PcAndState(i)->value(); | 11043 int pc_and_state = this->PcAndState(i)->value(); |
| 10951 PrintF("%6d %8d %s\n", | 11044 PrintF(out, "%6d %8d %s\n", |
| 10952 this->AstId(i).ToInt(), | 11045 this->AstId(i).ToInt(), |
| 10953 FullCodeGenerator::PcField::decode(pc_and_state), | 11046 FullCodeGenerator::PcField::decode(pc_and_state), |
| 10954 FullCodeGenerator::State2String( | 11047 FullCodeGenerator::State2String( |
| 10955 FullCodeGenerator::StateField::decode(pc_and_state))); | 11048 FullCodeGenerator::StateField::decode(pc_and_state))); |
| 10956 } | 11049 } |
| 10957 } | 11050 } |
| 10958 | 11051 |
| 10959 | 11052 |
| 10960 const char* Code::ICState2String(InlineCacheState state) { | 11053 const char* Code::ICState2String(InlineCacheState state) { |
| 10961 switch (state) { | 11054 switch (state) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11052 | 11145 |
| 11053 if (kind() == FUNCTION) { | 11146 if (kind() == FUNCTION) { |
| 11054 DeoptimizationOutputData* data = | 11147 DeoptimizationOutputData* data = |
| 11055 DeoptimizationOutputData::cast(this->deoptimization_data()); | 11148 DeoptimizationOutputData::cast(this->deoptimization_data()); |
| 11056 data->DeoptimizationOutputDataPrint(out); | 11149 data->DeoptimizationOutputDataPrint(out); |
| 11057 } else if (kind() == OPTIMIZED_FUNCTION) { | 11150 } else if (kind() == OPTIMIZED_FUNCTION) { |
| 11058 DeoptimizationInputData* data = | 11151 DeoptimizationInputData* data = |
| 11059 DeoptimizationInputData::cast(this->deoptimization_data()); | 11152 DeoptimizationInputData::cast(this->deoptimization_data()); |
| 11060 data->DeoptimizationInputDataPrint(out); | 11153 data->DeoptimizationInputDataPrint(out); |
| 11061 } | 11154 } |
| 11062 PrintF("\n"); | 11155 PrintF(out, "\n"); |
| 11063 | 11156 |
| 11064 if (is_crankshafted()) { | 11157 if (is_crankshafted()) { |
| 11065 SafepointTable table(this); | 11158 SafepointTable table(this); |
| 11066 PrintF(out, "Safepoints (size = %u)\n", table.size()); | 11159 PrintF(out, "Safepoints (size = %u)\n", table.size()); |
| 11067 for (unsigned i = 0; i < table.length(); i++) { | 11160 for (unsigned i = 0; i < table.length(); i++) { |
| 11068 unsigned pc_offset = table.GetPcOffset(i); | 11161 unsigned pc_offset = table.GetPcOffset(i); |
| 11069 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); | 11162 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); |
| 11070 table.PrintEntry(i); | 11163 table.PrintEntry(i, out); |
| 11071 PrintF(out, " (sp -> fp)"); | 11164 PrintF(out, " (sp -> fp)"); |
| 11072 SafepointEntry entry = table.GetEntry(i); | 11165 SafepointEntry entry = table.GetEntry(i); |
| 11073 if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) { | 11166 if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) { |
| 11074 PrintF(out, " %6d", entry.deoptimization_index()); | 11167 PrintF(out, " %6d", entry.deoptimization_index()); |
| 11075 } else { | 11168 } else { |
| 11076 PrintF(out, " <none>"); | 11169 PrintF(out, " <none>"); |
| 11077 } | 11170 } |
| 11078 if (entry.argument_count() > 0) { | 11171 if (entry.argument_count() > 0) { |
| 11079 PrintF(out, " argc: %d", entry.argument_count()); | 11172 PrintF(out, " argc: %d", entry.argument_count()); |
| 11080 } | 11173 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 11101 PrintF(out, "\n"); | 11194 PrintF(out, "\n"); |
| 11102 } | 11195 } |
| 11103 #ifdef OBJECT_PRINT | 11196 #ifdef OBJECT_PRINT |
| 11104 if (!type_feedback_info()->IsUndefined()) { | 11197 if (!type_feedback_info()->IsUndefined()) { |
| 11105 TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out); | 11198 TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out); |
| 11106 PrintF(out, "\n"); | 11199 PrintF(out, "\n"); |
| 11107 } | 11200 } |
| 11108 #endif | 11201 #endif |
| 11109 } | 11202 } |
| 11110 | 11203 |
| 11111 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 11204 PrintF(out, "RelocInfo (size = %d)\n", relocation_size()); |
| 11112 for (RelocIterator it(this); !it.done(); it.next()) { | 11205 for (RelocIterator it(this); !it.done(); it.next()) { |
| 11113 it.rinfo()->Print(GetIsolate(), out); | 11206 it.rinfo()->Print(GetIsolate(), out); |
| 11114 } | 11207 } |
| 11115 PrintF(out, "\n"); | 11208 PrintF(out, "\n"); |
| 11116 } | 11209 } |
| 11117 #endif // ENABLE_DISASSEMBLER | 11210 #endif // ENABLE_DISASSEMBLER |
| 11118 | 11211 |
| 11119 | 11212 |
| 11120 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 11213 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
| 11121 int capacity, | 11214 int capacity, |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11387 Handle<Object> hresult; | 11480 Handle<Object> hresult; |
| 11388 if (!result->ToHandle(&hresult, isolate)) return result; | 11481 if (!result->ToHandle(&hresult, isolate)) return result; |
| 11389 | 11482 |
| 11390 CHECK(self->length()->ToArrayIndex(&new_length)); | 11483 CHECK(self->length()->ToArrayIndex(&new_length)); |
| 11391 if (old_length == new_length) return *hresult; | 11484 if (old_length == new_length) return *hresult; |
| 11392 | 11485 |
| 11393 BeginPerformSplice(self); | 11486 BeginPerformSplice(self); |
| 11394 | 11487 |
| 11395 for (int i = 0; i < indices.length(); ++i) { | 11488 for (int i = 0; i < indices.length(); ++i) { |
| 11396 JSObject::EnqueueChangeRecord( | 11489 JSObject::EnqueueChangeRecord( |
| 11397 self, "deleted", isolate->factory()->Uint32ToString(indices[i]), | 11490 self, "delete", isolate->factory()->Uint32ToString(indices[i]), |
| 11398 old_values[i]); | 11491 old_values[i]); |
| 11399 } | 11492 } |
| 11400 JSObject::EnqueueChangeRecord( | 11493 JSObject::EnqueueChangeRecord( |
| 11401 self, "updated", isolate->factory()->length_string(), | 11494 self, "update", isolate->factory()->length_string(), |
| 11402 old_length_handle); | 11495 old_length_handle); |
| 11403 | 11496 |
| 11404 EndPerformSplice(self); | 11497 EndPerformSplice(self); |
| 11405 | 11498 |
| 11406 uint32_t index = Min(old_length, new_length); | 11499 uint32_t index = Min(old_length, new_length); |
| 11407 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; | 11500 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; |
| 11408 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; | 11501 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; |
| 11409 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | 11502 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
| 11410 if (delete_count > 0) { | 11503 if (delete_count > 0) { |
| 11411 for (int i = indices.length() - 1; i >= 0; i--) { | 11504 for (int i = indices.length() - 1; i >= 0; i--) { |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11739 pt = pt->GetPrototype(isolate)) { | 11832 pt = pt->GetPrototype(isolate)) { |
| 11740 if (JSReceiver::cast(pt) == *object) { | 11833 if (JSReceiver::cast(pt) == *object) { |
| 11741 // Cycle detected. | 11834 // Cycle detected. |
| 11742 Handle<Object> error = isolate->factory()->NewError( | 11835 Handle<Object> error = isolate->factory()->NewError( |
| 11743 "cyclic_proto", HandleVector<Object>(NULL, 0)); | 11836 "cyclic_proto", HandleVector<Object>(NULL, 0)); |
| 11744 isolate->Throw(*error); | 11837 isolate->Throw(*error); |
| 11745 return Handle<Object>(); | 11838 return Handle<Object>(); |
| 11746 } | 11839 } |
| 11747 } | 11840 } |
| 11748 | 11841 |
| 11842 bool dictionary_elements_in_chain = |
| 11843 object->map()->DictionaryElementsInPrototypeChainOnly(); |
| 11749 Handle<JSObject> real_receiver = object; | 11844 Handle<JSObject> real_receiver = object; |
| 11750 | 11845 |
| 11751 if (skip_hidden_prototypes) { | 11846 if (skip_hidden_prototypes) { |
| 11752 // Find the first object in the chain whose prototype object is not | 11847 // Find the first object in the chain whose prototype object is not |
| 11753 // hidden and set the new prototype on that object. | 11848 // hidden and set the new prototype on that object. |
| 11754 Object* current_proto = real_receiver->GetPrototype(); | 11849 Object* current_proto = real_receiver->GetPrototype(); |
| 11755 while (current_proto->IsJSObject() && | 11850 while (current_proto->IsJSObject() && |
| 11756 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { | 11851 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
| 11757 real_receiver = handle(JSObject::cast(current_proto), isolate); | 11852 real_receiver = handle(JSObject::cast(current_proto), isolate); |
| 11758 current_proto = current_proto->GetPrototype(isolate); | 11853 current_proto = current_proto->GetPrototype(isolate); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 11771 | 11866 |
| 11772 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); | 11867 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); |
| 11773 if (new_map.is_null()) { | 11868 if (new_map.is_null()) { |
| 11774 new_map = Map::Copy(map); | 11869 new_map = Map::Copy(map); |
| 11775 Map::PutPrototypeTransition(map, value, new_map); | 11870 Map::PutPrototypeTransition(map, value, new_map); |
| 11776 new_map->set_prototype(*value); | 11871 new_map->set_prototype(*value); |
| 11777 } | 11872 } |
| 11778 ASSERT(new_map->prototype() == *value); | 11873 ASSERT(new_map->prototype() == *value); |
| 11779 real_receiver->set_map(*new_map); | 11874 real_receiver->set_map(*new_map); |
| 11780 | 11875 |
| 11876 if (!dictionary_elements_in_chain && |
| 11877 new_map->DictionaryElementsInPrototypeChainOnly()) { |
| 11878 // If the prototype chain didn't previously have element callbacks, then |
| 11879 // KeyedStoreICs need to be cleared to ensure any that involve this |
| 11880 // map go generic. |
| 11881 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); |
| 11882 } |
| 11883 |
| 11781 heap->ClearInstanceofCache(); | 11884 heap->ClearInstanceofCache(); |
| 11782 ASSERT(size == object->Size()); | 11885 ASSERT(size == object->Size()); |
| 11783 return value; | 11886 return value; |
| 11784 } | 11887 } |
| 11785 | 11888 |
| 11786 | 11889 |
| 11787 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 11890 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
| 11788 uint32_t first_arg, | 11891 uint32_t first_arg, |
| 11789 uint32_t arg_count, | 11892 uint32_t arg_count, |
| 11790 EnsureElementsMode mode) { | 11893 EnsureElementsMode mode) { |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12426 object->SetElement(index, *value, NONE, strict_mode, false), | 12529 object->SetElement(index, *value, NONE, strict_mode, false), |
| 12427 Object); | 12530 Object); |
| 12428 } | 12531 } |
| 12429 | 12532 |
| 12430 | 12533 |
| 12431 Handle<Object> JSObject::SetElement(Handle<JSObject> object, | 12534 Handle<Object> JSObject::SetElement(Handle<JSObject> object, |
| 12432 uint32_t index, | 12535 uint32_t index, |
| 12433 Handle<Object> value, | 12536 Handle<Object> value, |
| 12434 PropertyAttributes attr, | 12537 PropertyAttributes attr, |
| 12435 StrictModeFlag strict_mode, | 12538 StrictModeFlag strict_mode, |
| 12539 bool check_prototype, |
| 12436 SetPropertyMode set_mode) { | 12540 SetPropertyMode set_mode) { |
| 12437 if (object->HasExternalArrayElements()) { | 12541 if (object->HasExternalArrayElements()) { |
| 12438 if (!value->IsNumber() && !value->IsUndefined()) { | 12542 if (!value->IsNumber() && !value->IsUndefined()) { |
| 12439 bool has_exception; | 12543 bool has_exception; |
| 12440 Handle<Object> number = | 12544 Handle<Object> number = |
| 12441 Execution::ToNumber(object->GetIsolate(), value, &has_exception); | 12545 Execution::ToNumber(object->GetIsolate(), value, &has_exception); |
| 12442 if (has_exception) return Handle<Object>(); | 12546 if (has_exception) return Handle<Object>(); |
| 12443 value = number; | 12547 value = number; |
| 12444 } | 12548 } |
| 12445 } | 12549 } |
| 12446 CALL_HEAP_FUNCTION( | 12550 CALL_HEAP_FUNCTION( |
| 12447 object->GetIsolate(), | 12551 object->GetIsolate(), |
| 12448 object->SetElement(index, *value, attr, strict_mode, true, set_mode), | 12552 object->SetElement(index, *value, attr, strict_mode, check_prototype, |
| 12553 set_mode), |
| 12449 Object); | 12554 Object); |
| 12450 } | 12555 } |
| 12451 | 12556 |
| 12452 | 12557 |
| 12453 MaybeObject* JSObject::SetElement(uint32_t index, | 12558 MaybeObject* JSObject::SetElement(uint32_t index, |
| 12454 Object* value_raw, | 12559 Object* value_raw, |
| 12455 PropertyAttributes attributes, | 12560 PropertyAttributes attributes, |
| 12456 StrictModeFlag strict_mode, | 12561 StrictModeFlag strict_mode, |
| 12457 bool check_prototype, | 12562 bool check_prototype, |
| 12458 SetPropertyMode set_mode) { | 12563 SetPropertyMode set_mode) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12537 if (self->IsJSArray() && | 12642 if (self->IsJSArray() && |
| 12538 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { | 12643 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { |
| 12539 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), | 12644 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), |
| 12540 isolate); | 12645 isolate); |
| 12541 uint32_t old_length = 0; | 12646 uint32_t old_length = 0; |
| 12542 uint32_t new_length = 0; | 12647 uint32_t new_length = 0; |
| 12543 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 12648 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
| 12544 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 12649 CHECK(new_length_handle->ToArrayIndex(&new_length)); |
| 12545 | 12650 |
| 12546 BeginPerformSplice(Handle<JSArray>::cast(self)); | 12651 BeginPerformSplice(Handle<JSArray>::cast(self)); |
| 12547 EnqueueChangeRecord(self, "new", name, old_value); | 12652 EnqueueChangeRecord(self, "add", name, old_value); |
| 12548 EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(), | 12653 EnqueueChangeRecord(self, "update", isolate->factory()->length_string(), |
| 12549 old_length_handle); | 12654 old_length_handle); |
| 12550 EndPerformSplice(Handle<JSArray>::cast(self)); | 12655 EndPerformSplice(Handle<JSArray>::cast(self)); |
| 12551 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | 12656 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
| 12552 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, | 12657 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, |
| 12553 new_length - old_length); | 12658 new_length - old_length); |
| 12554 } else { | 12659 } else { |
| 12555 EnqueueChangeRecord(self, "new", name, old_value); | 12660 EnqueueChangeRecord(self, "add", name, old_value); |
| 12556 } | 12661 } |
| 12557 } else if (old_value->IsTheHole()) { | 12662 } else if (old_value->IsTheHole()) { |
| 12558 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 12663 EnqueueChangeRecord(self, "reconfigure", name, old_value); |
| 12559 } else { | 12664 } else { |
| 12560 Handle<Object> new_value = Object::GetElement(isolate, self, index); | 12665 Handle<Object> new_value = Object::GetElement(isolate, self, index); |
| 12561 bool value_changed = !old_value->SameValue(*new_value); | 12666 bool value_changed = !old_value->SameValue(*new_value); |
| 12562 if (old_attributes != new_attributes) { | 12667 if (old_attributes != new_attributes) { |
| 12563 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 12668 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
| 12564 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 12669 EnqueueChangeRecord(self, "reconfigure", name, old_value); |
| 12565 } else if (value_changed) { | 12670 } else if (value_changed) { |
| 12566 EnqueueChangeRecord(self, "updated", name, old_value); | 12671 EnqueueChangeRecord(self, "update", name, old_value); |
| 12567 } | 12672 } |
| 12568 } | 12673 } |
| 12569 | 12674 |
| 12570 return *hresult; | 12675 return *hresult; |
| 12571 } | 12676 } |
| 12572 | 12677 |
| 12573 | 12678 |
| 12574 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 12679 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 12575 Object* value, | 12680 Object* value, |
| 12576 PropertyAttributes attr, | 12681 PropertyAttributes attr, |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12759 | 12864 |
| 12760 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 12865 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
| 12761 ASSERT(!map()->is_observed()); | 12866 ASSERT(!map()->is_observed()); |
| 12762 ElementsKind from_kind = map()->elements_kind(); | 12867 ElementsKind from_kind = map()->elements_kind(); |
| 12763 | 12868 |
| 12764 if (IsFastHoleyElementsKind(from_kind)) { | 12869 if (IsFastHoleyElementsKind(from_kind)) { |
| 12765 to_kind = GetHoleyElementsKind(to_kind); | 12870 to_kind = GetHoleyElementsKind(to_kind); |
| 12766 } | 12871 } |
| 12767 | 12872 |
| 12768 if (from_kind == to_kind) return this; | 12873 if (from_kind == to_kind) return this; |
| 12769 | 12874 // Don't update the site if to_kind isn't fast |
| 12770 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); | 12875 if (IsFastElementsKind(to_kind)) { |
| 12771 if (maybe_failure->IsFailure()) return maybe_failure; | 12876 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| 12877 if (maybe_failure->IsFailure()) return maybe_failure; |
| 12878 } |
| 12772 | 12879 |
| 12773 Isolate* isolate = GetIsolate(); | 12880 Isolate* isolate = GetIsolate(); |
| 12774 if (elements() == isolate->heap()->empty_fixed_array() || | 12881 if (elements() == isolate->heap()->empty_fixed_array() || |
| 12775 (IsFastSmiOrObjectElementsKind(from_kind) && | 12882 (IsFastSmiOrObjectElementsKind(from_kind) && |
| 12776 IsFastSmiOrObjectElementsKind(to_kind)) || | 12883 IsFastSmiOrObjectElementsKind(to_kind)) || |
| 12777 (from_kind == FAST_DOUBLE_ELEMENTS && | 12884 (from_kind == FAST_DOUBLE_ELEMENTS && |
| 12778 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 12885 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
| 12779 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 12886 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
| 12780 // No change is needed to the elements() buffer, the transition | 12887 // No change is needed to the elements() buffer, the transition |
| 12781 // only requires a map change. | 12888 // only requires a map change. |
| (...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14280 template | 14387 template |
| 14281 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements(); | 14388 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements(); |
| 14282 | 14389 |
| 14283 template | 14390 template |
| 14284 int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements(); | 14391 int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements(); |
| 14285 | 14392 |
| 14286 template | 14393 template |
| 14287 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t); | 14394 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t); |
| 14288 | 14395 |
| 14289 | 14396 |
| 14397 Handle<Object> JSObject::PrepareSlowElementsForSort( |
| 14398 Handle<JSObject> object, uint32_t limit) { |
| 14399 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 14400 object->PrepareSlowElementsForSort(limit), |
| 14401 Object); |
| 14402 } |
| 14403 |
| 14404 |
| 14290 // Collates undefined and unexisting elements below limit from position | 14405 // Collates undefined and unexisting elements below limit from position |
| 14291 // zero of the elements. The object stays in Dictionary mode. | 14406 // zero of the elements. The object stays in Dictionary mode. |
| 14292 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | 14407 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| 14293 ASSERT(HasDictionaryElements()); | 14408 ASSERT(HasDictionaryElements()); |
| 14294 // Must stay in dictionary mode, either because of requires_slow_elements, | 14409 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 14295 // or because we are not going to sort (and therefore compact) all of the | 14410 // or because we are not going to sort (and therefore compact) all of the |
| 14296 // elements. | 14411 // elements. |
| 14297 SeededNumberDictionary* dict = element_dictionary(); | 14412 SeededNumberDictionary* dict = element_dictionary(); |
| 14298 HeapNumber* result_double = NULL; | 14413 HeapNumber* result_double = NULL; |
| 14299 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 14414 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14382 ASSERT_NE(NULL, result_double); | 14497 ASSERT_NE(NULL, result_double); |
| 14383 result_double->set_value(static_cast<double>(result)); | 14498 result_double->set_value(static_cast<double>(result)); |
| 14384 return result_double; | 14499 return result_double; |
| 14385 } | 14500 } |
| 14386 | 14501 |
| 14387 | 14502 |
| 14388 // Collects all defined (non-hole) and non-undefined (array) elements at | 14503 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 14389 // the start of the elements array. | 14504 // the start of the elements array. |
| 14390 // If the object is in dictionary mode, it is converted to fast elements | 14505 // If the object is in dictionary mode, it is converted to fast elements |
| 14391 // mode. | 14506 // mode. |
| 14392 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { | 14507 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, |
| 14393 Heap* heap = GetHeap(); | 14508 uint32_t limit) { |
| 14509 Isolate* isolate = object->GetIsolate(); |
| 14394 | 14510 |
| 14395 ASSERT(!map()->is_observed()); | 14511 ASSERT(!object->map()->is_observed()); |
| 14396 if (HasDictionaryElements()) { | 14512 if (object->HasDictionaryElements()) { |
| 14397 // Convert to fast elements containing only the existing properties. | 14513 // Convert to fast elements containing only the existing properties. |
| 14398 // Ordering is irrelevant, since we are going to sort anyway. | 14514 // Ordering is irrelevant, since we are going to sort anyway. |
| 14399 SeededNumberDictionary* dict = element_dictionary(); | 14515 Handle<SeededNumberDictionary> dict(object->element_dictionary()); |
| 14400 if (IsJSArray() || dict->requires_slow_elements() || | 14516 if (object->IsJSArray() || dict->requires_slow_elements() || |
| 14401 dict->max_number_key() >= limit) { | 14517 dict->max_number_key() >= limit) { |
| 14402 return PrepareSlowElementsForSort(limit); | 14518 return JSObject::PrepareSlowElementsForSort(object, limit); |
| 14403 } | 14519 } |
| 14404 // Convert to fast elements. | 14520 // Convert to fast elements. |
| 14405 | 14521 |
| 14406 Object* obj; | 14522 Handle<Map> new_map = |
| 14407 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), | 14523 JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS); |
| 14408 FAST_HOLEY_ELEMENTS); | |
| 14409 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 14410 Map* new_map = Map::cast(obj); | |
| 14411 | 14524 |
| 14412 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; | 14525 PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ? |
| 14413 Object* new_array; | 14526 NOT_TENURED: TENURED; |
| 14414 { MaybeObject* maybe_new_array = | 14527 Handle<FixedArray> fast_elements = |
| 14415 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); | 14528 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure); |
| 14416 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 14529 dict->CopyValuesTo(*fast_elements); |
| 14417 } | 14530 object->ValidateElements(); |
| 14418 FixedArray* fast_elements = FixedArray::cast(new_array); | |
| 14419 dict->CopyValuesTo(fast_elements); | |
| 14420 ValidateElements(); | |
| 14421 | 14531 |
| 14422 set_map_and_elements(new_map, fast_elements); | 14532 object->set_map_and_elements(*new_map, *fast_elements); |
| 14423 } else if (HasExternalArrayElements()) { | 14533 } else if (object->HasExternalArrayElements()) { |
| 14424 // External arrays cannot have holes or undefined elements. | 14534 // External arrays cannot have holes or undefined elements. |
| 14425 return Smi::FromInt(ExternalArray::cast(elements())->length()); | 14535 return handle(Smi::FromInt( |
| 14426 } else if (!HasFastDoubleElements()) { | 14536 ExternalArray::cast(object->elements())->length()), isolate); |
| 14427 Object* obj; | 14537 } else if (!object->HasFastDoubleElements()) { |
| 14428 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 14538 JSObject::EnsureWritableFastElements(object); |
| 14429 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 14430 } | |
| 14431 } | 14539 } |
| 14432 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); | 14540 ASSERT(object->HasFastSmiOrObjectElements() || |
| 14541 object->HasFastDoubleElements()); |
| 14433 | 14542 |
| 14434 // Collect holes at the end, undefined before that and the rest at the | 14543 // Collect holes at the end, undefined before that and the rest at the |
| 14435 // start, and return the number of non-hole, non-undefined values. | 14544 // start, and return the number of non-hole, non-undefined values. |
| 14436 | 14545 |
| 14437 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); | 14546 Handle<FixedArrayBase> elements_base(object->elements()); |
| 14438 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 14547 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 14439 if (limit > elements_length) { | 14548 if (limit > elements_length) { |
| 14440 limit = elements_length ; | 14549 limit = elements_length ; |
| 14441 } | 14550 } |
| 14442 if (limit == 0) { | 14551 if (limit == 0) { |
| 14443 return Smi::FromInt(0); | 14552 return handle(Smi::FromInt(0), isolate); |
| 14444 } | |
| 14445 | |
| 14446 HeapNumber* result_double = NULL; | |
| 14447 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | |
| 14448 // Pessimistically allocate space for return value before | |
| 14449 // we start mutating the array. | |
| 14450 Object* new_double; | |
| 14451 { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); | |
| 14452 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | |
| 14453 } | |
| 14454 result_double = HeapNumber::cast(new_double); | |
| 14455 } | 14553 } |
| 14456 | 14554 |
| 14457 uint32_t result = 0; | 14555 uint32_t result = 0; |
| 14458 if (elements_base->map() == heap->fixed_double_array_map()) { | 14556 if (elements_base->map() == isolate->heap()->fixed_double_array_map()) { |
| 14459 FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base); | 14557 FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base); |
| 14460 // Split elements into defined and the_hole, in that order. | 14558 // Split elements into defined and the_hole, in that order. |
| 14461 unsigned int holes = limit; | 14559 unsigned int holes = limit; |
| 14462 // Assume most arrays contain no holes and undefined values, so minimize the | 14560 // Assume most arrays contain no holes and undefined values, so minimize the |
| 14463 // number of stores of non-undefined, non-the-hole values. | 14561 // number of stores of non-undefined, non-the-hole values. |
| 14464 for (unsigned int i = 0; i < holes; i++) { | 14562 for (unsigned int i = 0; i < holes; i++) { |
| 14465 if (elements->is_the_hole(i)) { | 14563 if (elements->is_the_hole(i)) { |
| 14466 holes--; | 14564 holes--; |
| 14467 } else { | 14565 } else { |
| 14468 continue; | 14566 continue; |
| 14469 } | 14567 } |
| 14470 // Position i needs to be filled. | 14568 // Position i needs to be filled. |
| 14471 while (holes > i) { | 14569 while (holes > i) { |
| 14472 if (elements->is_the_hole(holes)) { | 14570 if (elements->is_the_hole(holes)) { |
| 14473 holes--; | 14571 holes--; |
| 14474 } else { | 14572 } else { |
| 14475 elements->set(i, elements->get_scalar(holes)); | 14573 elements->set(i, elements->get_scalar(holes)); |
| 14476 break; | 14574 break; |
| 14477 } | 14575 } |
| 14478 } | 14576 } |
| 14479 } | 14577 } |
| 14480 result = holes; | 14578 result = holes; |
| 14481 while (holes < limit) { | 14579 while (holes < limit) { |
| 14482 elements->set_the_hole(holes); | 14580 elements->set_the_hole(holes); |
| 14483 holes++; | 14581 holes++; |
| 14484 } | 14582 } |
| 14485 } else { | 14583 } else { |
| 14486 FixedArray* elements = FixedArray::cast(elements_base); | 14584 FixedArray* elements = FixedArray::cast(*elements_base); |
| 14487 DisallowHeapAllocation no_gc; | 14585 DisallowHeapAllocation no_gc; |
| 14488 | 14586 |
| 14489 // Split elements into defined, undefined and the_hole, in that order. Only | 14587 // Split elements into defined, undefined and the_hole, in that order. Only |
| 14490 // count locations for undefined and the hole, and fill them afterwards. | 14588 // count locations for undefined and the hole, and fill them afterwards. |
| 14491 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc); | 14589 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc); |
| 14492 unsigned int undefs = limit; | 14590 unsigned int undefs = limit; |
| 14493 unsigned int holes = limit; | 14591 unsigned int holes = limit; |
| 14494 // Assume most arrays contain no holes and undefined values, so minimize the | 14592 // Assume most arrays contain no holes and undefined values, so minimize the |
| 14495 // number of stores of non-undefined, non-the-hole values. | 14593 // number of stores of non-undefined, non-the-hole values. |
| 14496 for (unsigned int i = 0; i < undefs; i++) { | 14594 for (unsigned int i = 0; i < undefs; i++) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 14521 while (undefs < holes) { | 14619 while (undefs < holes) { |
| 14522 elements->set_undefined(undefs); | 14620 elements->set_undefined(undefs); |
| 14523 undefs++; | 14621 undefs++; |
| 14524 } | 14622 } |
| 14525 while (holes < limit) { | 14623 while (holes < limit) { |
| 14526 elements->set_the_hole(holes); | 14624 elements->set_the_hole(holes); |
| 14527 holes++; | 14625 holes++; |
| 14528 } | 14626 } |
| 14529 } | 14627 } |
| 14530 | 14628 |
| 14531 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 14629 return isolate->factory()->NewNumberFromUint(result); |
| 14532 return Smi::FromInt(static_cast<int>(result)); | |
| 14533 } | |
| 14534 ASSERT_NE(NULL, result_double); | |
| 14535 result_double->set_value(static_cast<double>(result)); | |
| 14536 return result_double; | |
| 14537 } | 14630 } |
| 14538 | 14631 |
| 14539 | 14632 |
| 14540 ExternalArrayType JSTypedArray::type() { | 14633 ExternalArrayType JSTypedArray::type() { |
| 14541 switch (elements()->map()->instance_type()) { | 14634 switch (elements()->map()->instance_type()) { |
| 14542 case EXTERNAL_BYTE_ARRAY_TYPE: | 14635 case EXTERNAL_BYTE_ARRAY_TYPE: |
| 14543 return kExternalByteArray; | 14636 return kExternalByteArray; |
| 14544 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | 14637 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
| 14545 return kExternalUnsignedByteArray; | 14638 return kExternalUnsignedByteArray; |
| 14546 case EXTERNAL_SHORT_ARRAY_TYPE: | 14639 case EXTERNAL_SHORT_ARRAY_TYPE: |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14744 } | 14837 } |
| 14745 | 14838 |
| 14746 | 14839 |
| 14747 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 14840 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 14748 ASSERT(!HasFastProperties()); | 14841 ASSERT(!HasFastProperties()); |
| 14749 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 14842 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 14750 return PropertyCell::cast(value); | 14843 return PropertyCell::cast(value); |
| 14751 } | 14844 } |
| 14752 | 14845 |
| 14753 | 14846 |
| 14754 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 14847 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell( |
| 14755 Handle<GlobalObject> global, | 14848 Handle<JSGlobalObject> global, |
| 14756 Handle<Name> name) { | 14849 Handle<Name> name) { |
| 14757 ASSERT(!global->HasFastProperties()); | 14850 ASSERT(!global->HasFastProperties()); |
| 14758 int entry = global->property_dictionary()->FindEntry(*name); | 14851 int entry = global->property_dictionary()->FindEntry(*name); |
| 14759 if (entry == NameDictionary::kNotFound) { | 14852 if (entry == NameDictionary::kNotFound) { |
| 14760 Isolate* isolate = global->GetIsolate(); | 14853 Isolate* isolate = global->GetIsolate(); |
| 14761 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( | 14854 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( |
| 14762 isolate->factory()->the_hole_value()); | 14855 isolate->factory()->the_hole_value()); |
| 14763 PropertyDetails details(NONE, NORMAL, 0); | 14856 PropertyDetails details(NONE, NORMAL, 0); |
| 14764 details = details.AsDeleted(); | 14857 details = details.AsDeleted(); |
| 14765 Handle<NameDictionary> dictionary = NameDictionaryAdd( | 14858 Handle<NameDictionary> dictionary = NameDictionaryAdd( |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15133 | 15226 |
| 15134 template<typename Shape, typename Key> | 15227 template<typename Shape, typename Key> |
| 15135 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, | 15228 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap, |
| 15136 int at_least_space_for, | 15229 int at_least_space_for, |
| 15137 PretenureFlag pretenure) { | 15230 PretenureFlag pretenure) { |
| 15138 Object* obj; | 15231 Object* obj; |
| 15139 { MaybeObject* maybe_obj = | 15232 { MaybeObject* maybe_obj = |
| 15140 HashTable<Shape, Key>::Allocate( | 15233 HashTable<Shape, Key>::Allocate( |
| 15141 heap, | 15234 heap, |
| 15142 at_least_space_for, | 15235 at_least_space_for, |
| 15143 HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY, | 15236 USE_DEFAULT_MINIMUM_CAPACITY, |
| 15144 pretenure); | 15237 pretenure); |
| 15145 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15238 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 15146 } | 15239 } |
| 15147 // Initialize the next enumeration index. | 15240 // Initialize the next enumeration index. |
| 15148 Dictionary<Shape, Key>::cast(obj)-> | 15241 Dictionary<Shape, Key>::cast(obj)-> |
| 15149 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 15242 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 15150 return obj; | 15243 return obj; |
| 15151 } | 15244 } |
| 15152 | 15245 |
| 15153 | 15246 |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15699 obj->set_properties(fields); | 15792 obj->set_properties(fields); |
| 15700 ASSERT(obj->IsJSObject()); | 15793 ASSERT(obj->IsJSObject()); |
| 15701 | 15794 |
| 15702 // Check that it really works. | 15795 // Check that it really works. |
| 15703 ASSERT(obj->HasFastProperties()); | 15796 ASSERT(obj->HasFastProperties()); |
| 15704 | 15797 |
| 15705 return obj; | 15798 return obj; |
| 15706 } | 15799 } |
| 15707 | 15800 |
| 15708 | 15801 |
| 15802 Handle<ObjectHashSet> ObjectHashSet::EnsureCapacity( |
| 15803 Handle<ObjectHashSet> table, |
| 15804 int n, |
| 15805 Handle<Object> key, |
| 15806 PretenureFlag pretenure) { |
| 15807 Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table; |
| 15808 CALL_HEAP_FUNCTION(table_base->GetIsolate(), |
| 15809 table_base->EnsureCapacity(n, *key, pretenure), |
| 15810 ObjectHashSet); |
| 15811 } |
| 15812 |
| 15813 |
| 15814 Handle<ObjectHashSet> ObjectHashSet::Shrink(Handle<ObjectHashSet> table, |
| 15815 Handle<Object> key) { |
| 15816 Handle<HashTable<ObjectHashTableShape<1>, Object*> > table_base = table; |
| 15817 CALL_HEAP_FUNCTION(table_base->GetIsolate(), |
| 15818 table_base->Shrink(*key), |
| 15819 ObjectHashSet); |
| 15820 } |
| 15821 |
| 15822 |
| 15709 bool ObjectHashSet::Contains(Object* key) { | 15823 bool ObjectHashSet::Contains(Object* key) { |
| 15710 ASSERT(IsKey(key)); | 15824 ASSERT(IsKey(key)); |
| 15711 | 15825 |
| 15712 // If the object does not have an identity hash, it was never used as a key. | 15826 // If the object does not have an identity hash, it was never used as a key. |
| 15713 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); | 15827 Object* hash = key->GetHash(); |
| 15714 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false; | 15828 if (hash->IsUndefined()) return false; |
| 15715 } | 15829 |
| 15716 return (FindEntry(key) != kNotFound); | 15830 return (FindEntry(key) != kNotFound); |
| 15717 } | 15831 } |
| 15718 | 15832 |
| 15719 | 15833 |
| 15720 MaybeObject* ObjectHashSet::Add(Object* key) { | 15834 Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> table, |
| 15721 ASSERT(IsKey(key)); | 15835 Handle<Object> key) { |
| 15836 ASSERT(table->IsKey(*key)); |
| 15722 | 15837 |
| 15723 // Make sure the key object has an identity hash code. | 15838 // Make sure the key object has an identity hash code. |
| 15724 int hash; | 15839 Handle<Object> object_hash = Object::GetOrCreateHash(key, |
| 15725 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); | 15840 table->GetIsolate()); |
| 15726 if (maybe_hash->IsFailure()) return maybe_hash; | 15841 |
| 15727 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); | 15842 int entry = table->FindEntry(*key); |
| 15728 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | |
| 15729 } | |
| 15730 int entry = FindEntry(key); | |
| 15731 | 15843 |
| 15732 // Check whether key is already present. | 15844 // Check whether key is already present. |
| 15733 if (entry != kNotFound) return this; | 15845 if (entry != kNotFound) return table; |
| 15734 | 15846 |
| 15735 // Check whether the hash set should be extended and add entry. | 15847 // Check whether the hash set should be extended and add entry. |
| 15736 Object* obj; | 15848 Handle<ObjectHashSet> new_table = |
| 15737 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 15849 ObjectHashSet::EnsureCapacity(table, 1, key); |
| 15738 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15850 entry = new_table->FindInsertionEntry(Smi::cast(*object_hash)->value()); |
| 15739 } | 15851 new_table->set(EntryToIndex(entry), *key); |
| 15740 ObjectHashSet* table = ObjectHashSet::cast(obj); | 15852 new_table->ElementAdded(); |
| 15741 entry = table->FindInsertionEntry(hash); | 15853 return new_table; |
| 15742 table->set(EntryToIndex(entry), key); | |
| 15743 table->ElementAdded(); | |
| 15744 return table; | |
| 15745 } | 15854 } |
| 15746 | 15855 |
| 15747 | 15856 |
| 15748 MaybeObject* ObjectHashSet::Remove(Object* key) { | 15857 Handle<ObjectHashSet> ObjectHashSet::Remove(Handle<ObjectHashSet> table, |
| 15749 ASSERT(IsKey(key)); | 15858 Handle<Object> key) { |
| 15859 ASSERT(table->IsKey(*key)); |
| 15750 | 15860 |
| 15751 // If the object does not have an identity hash, it was never used as a key. | 15861 // If the object does not have an identity hash, it was never used as a key. |
| 15752 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); | 15862 if (key->GetHash()->IsUndefined()) return table; |
| 15753 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this; | 15863 |
| 15754 } | 15864 int entry = table->FindEntry(*key); |
| 15755 int entry = FindEntry(key); | |
| 15756 | 15865 |
| 15757 // Check whether key is actually present. | 15866 // Check whether key is actually present. |
| 15758 if (entry == kNotFound) return this; | 15867 if (entry == kNotFound) return table; |
| 15759 | 15868 |
| 15760 // Remove entry and try to shrink this hash set. | 15869 // Remove entry and try to shrink this hash set. |
| 15761 set_the_hole(EntryToIndex(entry)); | 15870 table->set_the_hole(EntryToIndex(entry)); |
| 15762 ElementRemoved(); | 15871 table->ElementRemoved(); |
| 15763 return Shrink(key); | 15872 |
| 15873 return ObjectHashSet::Shrink(table, key); |
| 15764 } | 15874 } |
| 15765 | 15875 |
| 15766 | 15876 |
| 15877 Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity( |
| 15878 Handle<ObjectHashTable> table, |
| 15879 int n, |
| 15880 Handle<Object> key, |
| 15881 PretenureFlag pretenure) { |
| 15882 Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table; |
| 15883 CALL_HEAP_FUNCTION(table_base->GetIsolate(), |
| 15884 table_base->EnsureCapacity(n, *key, pretenure), |
| 15885 ObjectHashTable); |
| 15886 } |
| 15887 |
| 15888 |
| 15889 Handle<ObjectHashTable> ObjectHashTable::Shrink( |
| 15890 Handle<ObjectHashTable> table, Handle<Object> key) { |
| 15891 Handle<HashTable<ObjectHashTableShape<2>, Object*> > table_base = table; |
| 15892 CALL_HEAP_FUNCTION(table_base->GetIsolate(), |
| 15893 table_base->Shrink(*key), |
| 15894 ObjectHashTable); |
| 15895 } |
| 15896 |
| 15897 |
| 15767 Object* ObjectHashTable::Lookup(Object* key) { | 15898 Object* ObjectHashTable::Lookup(Object* key) { |
| 15768 ASSERT(IsKey(key)); | 15899 ASSERT(IsKey(key)); |
| 15769 | 15900 |
| 15770 // If the object does not have an identity hash, it was never used as a key. | 15901 // If the object does not have an identity hash, it was never used as a key. |
| 15771 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); | 15902 Object* hash = key->GetHash(); |
| 15772 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) { | 15903 if (hash->IsUndefined()) { |
| 15773 return GetHeap()->the_hole_value(); | 15904 return GetHeap()->the_hole_value(); |
| 15774 } | |
| 15775 } | 15905 } |
| 15776 int entry = FindEntry(key); | 15906 int entry = FindEntry(key); |
| 15777 if (entry == kNotFound) return GetHeap()->the_hole_value(); | 15907 if (entry == kNotFound) return GetHeap()->the_hole_value(); |
| 15778 return get(EntryToIndex(entry) + 1); | 15908 return get(EntryToIndex(entry) + 1); |
| 15779 } | 15909 } |
| 15780 | 15910 |
| 15781 | 15911 |
| 15782 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { | 15912 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
| 15783 ASSERT(IsKey(key)); | 15913 Handle<Object> key, |
| 15914 Handle<Object> value) { |
| 15915 ASSERT(table->IsKey(*key)); |
| 15916 |
| 15917 Isolate* isolate = table->GetIsolate(); |
| 15784 | 15918 |
| 15785 // Make sure the key object has an identity hash code. | 15919 // Make sure the key object has an identity hash code. |
| 15786 int hash; | 15920 Handle<Object> hash = Object::GetOrCreateHash(key, isolate); |
| 15787 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); | 15921 |
| 15788 if (maybe_hash->IsFailure()) return maybe_hash; | 15922 int entry = table->FindEntry(*key); |
| 15789 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); | |
| 15790 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | |
| 15791 } | |
| 15792 int entry = FindEntry(key); | |
| 15793 | 15923 |
| 15794 // Check whether to perform removal operation. | 15924 // Check whether to perform removal operation. |
| 15795 if (value->IsTheHole()) { | 15925 if (value->IsTheHole()) { |
| 15796 if (entry == kNotFound) return this; | 15926 if (entry == kNotFound) return table; |
| 15797 RemoveEntry(entry); | 15927 table->RemoveEntry(entry); |
| 15798 return Shrink(key); | 15928 return Shrink(table, key); |
| 15799 } | 15929 } |
| 15800 | 15930 |
| 15801 // Key is already in table, just overwrite value. | 15931 // Key is already in table, just overwrite value. |
| 15802 if (entry != kNotFound) { | 15932 if (entry != kNotFound) { |
| 15803 set(EntryToIndex(entry) + 1, value); | 15933 table->set(EntryToIndex(entry) + 1, *value); |
| 15804 return this; | 15934 return table; |
| 15805 } | 15935 } |
| 15806 | 15936 |
| 15807 // Check whether the hash table should be extended. | 15937 // Check whether the hash table should be extended. |
| 15808 Object* obj; | 15938 table = EnsureCapacity(table, 1, key); |
| 15809 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 15939 table->AddEntry(table->FindInsertionEntry(Handle<Smi>::cast(hash)->value()), |
| 15810 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15940 *key, |
| 15811 } | 15941 *value); |
| 15812 ObjectHashTable* table = ObjectHashTable::cast(obj); | |
| 15813 table->AddEntry(table->FindInsertionEntry(hash), key, value); | |
| 15814 return table; | 15942 return table; |
| 15815 } | 15943 } |
| 15816 | 15944 |
| 15817 | 15945 |
| 15818 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { | 15946 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { |
| 15819 set(EntryToIndex(entry), key); | 15947 set(EntryToIndex(entry), key); |
| 15820 set(EntryToIndex(entry) + 1, value); | 15948 set(EntryToIndex(entry) + 1, value); |
| 15821 ElementAdded(); | 15949 ElementAdded(); |
| 15822 } | 15950 } |
| 15823 | 15951 |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16398 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16526 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16399 static const char* error_messages_[] = { | 16527 static const char* error_messages_[] = { |
| 16400 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16528 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16401 }; | 16529 }; |
| 16402 #undef ERROR_MESSAGES_TEXTS | 16530 #undef ERROR_MESSAGES_TEXTS |
| 16403 return error_messages_[reason]; | 16531 return error_messages_[reason]; |
| 16404 } | 16532 } |
| 16405 | 16533 |
| 16406 | 16534 |
| 16407 } } // namespace v8::internal | 16535 } } // namespace v8::internal |
| OLD | NEW |