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

Side by Side Diff: src/objects.cc

Issue 71163006: Merge bleeding_edge r17376:17693. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Fix all.gyp Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698