| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <sstream> | 5 #include <sstream> |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
| 10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
| (...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 if (object->IsGlobalObject()) { | 701 if (object->IsGlobalObject()) { |
| 702 PropertyDetails details = dictionary->DetailsAt(entry); | 702 PropertyDetails details = dictionary->DetailsAt(entry); |
| 703 if (!details.IsConfigurable()) { | 703 if (!details.IsConfigurable()) { |
| 704 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); | 704 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); |
| 705 // When forced to delete global properties, we have to make a | 705 // When forced to delete global properties, we have to make a |
| 706 // map change to invalidate any ICs that think they can load | 706 // map change to invalidate any ICs that think they can load |
| 707 // from the non-configurable cell without checking if it contains | 707 // from the non-configurable cell without checking if it contains |
| 708 // the hole value. | 708 // the hole value. |
| 709 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 709 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 710 DCHECK(new_map->is_dictionary_map()); | 710 DCHECK(new_map->is_dictionary_map()); |
| 711 #if TRACE_MAPS |
| 712 if (FLAG_trace_maps) { |
| 713 PrintF("[TraceMaps: GlobalDeleteNormalized from= %p to= %p ]\n", |
| 714 reinterpret_cast<void*>(object->map()), |
| 715 reinterpret_cast<void*>(*new_map)); |
| 716 } |
| 717 #endif |
| 711 JSObject::MigrateToMap(object, new_map); | 718 JSObject::MigrateToMap(object, new_map); |
| 712 } | 719 } |
| 713 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 720 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 714 Handle<Object> value = isolate->factory()->the_hole_value(); | 721 Handle<Object> value = isolate->factory()->the_hole_value(); |
| 715 PropertyCell::SetValueInferType(cell, value); | 722 PropertyCell::SetValueInferType(cell, value); |
| 716 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 723 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 717 } else { | 724 } else { |
| 718 Handle<Object> deleted( | 725 Handle<Object> deleted( |
| 719 NameDictionary::DeleteProperty(dictionary, entry, mode)); | 726 NameDictionary::DeleteProperty(dictionary, entry, mode)); |
| 720 if (*deleted == isolate->heap()->true_value()) { | 727 if (*deleted == isolate->heap()->true_value()) { |
| (...skipping 1422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2143 return result; | 2150 return result; |
| 2144 } | 2151 } |
| 2145 | 2152 |
| 2146 | 2153 |
| 2147 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, | 2154 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
| 2148 int modify_index, | 2155 int modify_index, |
| 2149 StoreMode store_mode, | 2156 StoreMode store_mode, |
| 2150 PropertyAttributes attributes, | 2157 PropertyAttributes attributes, |
| 2151 const char* reason) { | 2158 const char* reason) { |
| 2152 Isolate* isolate = map->GetIsolate(); | 2159 Isolate* isolate = map->GetIsolate(); |
| 2153 Handle<Map> new_map = Copy(map); | 2160 Handle<Map> new_map = Copy(map, reason); |
| 2154 | 2161 |
| 2155 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2162 DescriptorArray* descriptors = new_map->instance_descriptors(); |
| 2156 int length = descriptors->number_of_descriptors(); | 2163 int length = descriptors->number_of_descriptors(); |
| 2157 for (int i = 0; i < length; i++) { | 2164 for (int i = 0; i < length; i++) { |
| 2158 descriptors->SetRepresentation(i, Representation::Tagged()); | 2165 descriptors->SetRepresentation(i, Representation::Tagged()); |
| 2159 if (descriptors->GetDetails(i).type() == FIELD) { | 2166 if (descriptors->GetDetails(i).type() == FIELD) { |
| 2160 descriptors->SetValue(i, HeapType::Any()); | 2167 descriptors->SetValue(i, HeapType::Any()); |
| 2161 } | 2168 } |
| 2162 } | 2169 } |
| 2163 | 2170 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2452 old_descriptors->GetFieldType(modify_index), *new_field_type); | 2459 old_descriptors->GetFieldType(modify_index), *new_field_type); |
| 2453 } | 2460 } |
| 2454 old_descriptors->SetRepresentation(modify_index, new_representation); | 2461 old_descriptors->SetRepresentation(modify_index, new_representation); |
| 2455 old_descriptors->SetValue(modify_index, *new_field_type); | 2462 old_descriptors->SetValue(modify_index, *new_field_type); |
| 2456 return old_map; | 2463 return old_map; |
| 2457 } | 2464 } |
| 2458 | 2465 |
| 2459 // Check the state of the root map. | 2466 // Check the state of the root map. |
| 2460 Handle<Map> root_map(old_map->FindRootMap(), isolate); | 2467 Handle<Map> root_map(old_map->FindRootMap(), isolate); |
| 2461 if (!old_map->EquivalentToForTransition(*root_map)) { | 2468 if (!old_map->EquivalentToForTransition(*root_map)) { |
| 2462 return CopyGeneralizeAllRepresentations( | 2469 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2463 old_map, modify_index, store_mode, "not equivalent"); | 2470 "GenAll_NotEquivalent"); |
| 2464 } | 2471 } |
| 2465 int root_nof = root_map->NumberOfOwnDescriptors(); | 2472 int root_nof = root_map->NumberOfOwnDescriptors(); |
| 2466 if (modify_index < root_nof) { | 2473 if (modify_index < root_nof) { |
| 2467 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2474 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2468 if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) || | 2475 if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) || |
| 2469 (old_details.type() == FIELD && | 2476 (old_details.type() == FIELD && |
| 2470 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || | 2477 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || |
| 2471 !new_representation.fits_into(old_details.representation())))) { | 2478 !new_representation.fits_into(old_details.representation())))) { |
| 2472 return CopyGeneralizeAllRepresentations( | 2479 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2473 old_map, modify_index, store_mode, "root modification"); | 2480 "GenAll_RootModification"); |
| 2474 } | 2481 } |
| 2475 } | 2482 } |
| 2476 | 2483 |
| 2477 Handle<Map> target_map = root_map; | 2484 Handle<Map> target_map = root_map; |
| 2478 for (int i = root_nof; i < old_nof; ++i) { | 2485 for (int i = root_nof; i < old_nof; ++i) { |
| 2479 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2486 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2480 int j = target_map->SearchTransition(old_details.type(), | 2487 int j = target_map->SearchTransition(old_details.type(), |
| 2481 old_descriptors->GetKey(i), | 2488 old_descriptors->GetKey(i), |
| 2482 old_details.attributes()); | 2489 old_details.attributes()); |
| 2483 if (j == TransitionArray::kNotFound) break; | 2490 if (j == TransitionArray::kNotFound) break; |
| 2484 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2491 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
| 2485 Handle<DescriptorArray> tmp_descriptors = handle( | 2492 Handle<DescriptorArray> tmp_descriptors = handle( |
| 2486 tmp_map->instance_descriptors(), isolate); | 2493 tmp_map->instance_descriptors(), isolate); |
| 2487 | 2494 |
| 2488 // Check if target map is incompatible. | 2495 // Check if target map is incompatible. |
| 2489 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2496 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 2490 PropertyType old_type = old_details.type(); | 2497 PropertyType old_type = old_details.type(); |
| 2491 PropertyType tmp_type = tmp_details.type(); | 2498 PropertyType tmp_type = tmp_details.type(); |
| 2492 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 2499 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
| 2493 if ((tmp_type == CALLBACKS || old_type == CALLBACKS) && | 2500 if ((tmp_type == CALLBACKS || old_type == CALLBACKS) && |
| 2494 (tmp_type != old_type || | 2501 (tmp_type != old_type || |
| 2495 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | 2502 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
| 2496 return CopyGeneralizeAllRepresentations( | 2503 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2497 old_map, modify_index, store_mode, "incompatible"); | 2504 "GenAll_Incompatible"); |
| 2498 } | 2505 } |
| 2499 Representation old_representation = old_details.representation(); | 2506 Representation old_representation = old_details.representation(); |
| 2500 Representation tmp_representation = tmp_details.representation(); | 2507 Representation tmp_representation = tmp_details.representation(); |
| 2501 if (!old_representation.fits_into(tmp_representation) || | 2508 if (!old_representation.fits_into(tmp_representation) || |
| 2502 (!new_representation.fits_into(tmp_representation) && | 2509 (!new_representation.fits_into(tmp_representation) && |
| 2503 modify_index == i)) { | 2510 modify_index == i)) { |
| 2504 break; | 2511 break; |
| 2505 } | 2512 } |
| 2506 if (tmp_type == FIELD) { | 2513 if (tmp_type == FIELD) { |
| 2507 // Generalize the field type as necessary. | 2514 // Generalize the field type as necessary. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2552 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2559 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
| 2553 Handle<DescriptorArray> tmp_descriptors( | 2560 Handle<DescriptorArray> tmp_descriptors( |
| 2554 tmp_map->instance_descriptors(), isolate); | 2561 tmp_map->instance_descriptors(), isolate); |
| 2555 | 2562 |
| 2556 // Check if target map is compatible. | 2563 // Check if target map is compatible. |
| 2557 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2564 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 2558 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 2565 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
| 2559 if ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && | 2566 if ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && |
| 2560 (tmp_details.type() != old_details.type() || | 2567 (tmp_details.type() != old_details.type() || |
| 2561 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | 2568 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
| 2562 return CopyGeneralizeAllRepresentations( | 2569 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2563 old_map, modify_index, store_mode, "incompatible"); | 2570 "GenAll_Incompatible"); |
| 2564 } | 2571 } |
| 2565 target_map = tmp_map; | 2572 target_map = tmp_map; |
| 2566 } | 2573 } |
| 2567 target_nof = target_map->NumberOfOwnDescriptors(); | 2574 target_nof = target_map->NumberOfOwnDescriptors(); |
| 2568 target_descriptors = handle(target_map->instance_descriptors(), isolate); | 2575 target_descriptors = handle(target_map->instance_descriptors(), isolate); |
| 2569 | 2576 |
| 2570 // Allocate a new descriptor array large enough to hold the required | 2577 // Allocate a new descriptor array large enough to hold the required |
| 2571 // descriptors, with minimally the exact same size as the old descriptor | 2578 // descriptors, with minimally the exact same size as the old descriptor |
| 2572 // array. | 2579 // array. |
| 2573 int new_slack = Max( | 2580 int new_slack = Max( |
| (...skipping 1679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4253 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object, | 4260 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object, |
| 4254 Handle<Name> name, | 4261 Handle<Name> name, |
| 4255 Handle<Code> code) { | 4262 Handle<Code> code) { |
| 4256 Handle<Map> map(object->map()); | 4263 Handle<Map> map(object->map()); |
| 4257 Map::UpdateCodeCache(map, name, code); | 4264 Map::UpdateCodeCache(map, name, code); |
| 4258 } | 4265 } |
| 4259 | 4266 |
| 4260 | 4267 |
| 4261 void JSObject::NormalizeProperties(Handle<JSObject> object, | 4268 void JSObject::NormalizeProperties(Handle<JSObject> object, |
| 4262 PropertyNormalizationMode mode, | 4269 PropertyNormalizationMode mode, |
| 4263 int expected_additional_properties) { | 4270 int expected_additional_properties, |
| 4271 const char* reason) { |
| 4264 if (!object->HasFastProperties()) return; | 4272 if (!object->HasFastProperties()) return; |
| 4265 | 4273 |
| 4266 Handle<Map> map(object->map()); | 4274 Handle<Map> map(object->map()); |
| 4267 Handle<Map> new_map = Map::Normalize(map, mode); | 4275 Handle<Map> new_map = Map::Normalize(map, mode, reason); |
| 4268 | 4276 |
| 4269 MigrateFastToSlow(object, new_map, expected_additional_properties); | 4277 MigrateFastToSlow(object, new_map, expected_additional_properties); |
| 4270 } | 4278 } |
| 4271 | 4279 |
| 4272 | 4280 |
| 4273 void JSObject::MigrateFastToSlow(Handle<JSObject> object, | 4281 void JSObject::MigrateFastToSlow(Handle<JSObject> object, |
| 4274 Handle<Map> new_map, | 4282 Handle<Map> new_map, |
| 4275 int expected_additional_properties) { | 4283 int expected_additional_properties) { |
| 4276 // The global object is always normalized. | 4284 // The global object is always normalized. |
| 4277 DCHECK(!object->IsGlobalObject()); | 4285 DCHECK(!object->IsGlobalObject()); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4365 if (FLAG_trace_normalization) { | 4373 if (FLAG_trace_normalization) { |
| 4366 OFStream os(stdout); | 4374 OFStream os(stdout); |
| 4367 os << "Object properties have been normalized:\n"; | 4375 os << "Object properties have been normalized:\n"; |
| 4368 object->Print(os); | 4376 object->Print(os); |
| 4369 } | 4377 } |
| 4370 #endif | 4378 #endif |
| 4371 } | 4379 } |
| 4372 | 4380 |
| 4373 | 4381 |
| 4374 void JSObject::MigrateSlowToFast(Handle<JSObject> object, | 4382 void JSObject::MigrateSlowToFast(Handle<JSObject> object, |
| 4375 int unused_property_fields) { | 4383 int unused_property_fields, |
| 4384 const char* reason) { |
| 4376 if (object->HasFastProperties()) return; | 4385 if (object->HasFastProperties()) return; |
| 4377 DCHECK(!object->IsGlobalObject()); | 4386 DCHECK(!object->IsGlobalObject()); |
| 4378 Isolate* isolate = object->GetIsolate(); | 4387 Isolate* isolate = object->GetIsolate(); |
| 4379 Factory* factory = isolate->factory(); | 4388 Factory* factory = isolate->factory(); |
| 4380 Handle<NameDictionary> dictionary(object->property_dictionary()); | 4389 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 4381 | 4390 |
| 4382 // Make sure we preserve dictionary representation if there are too many | 4391 // Make sure we preserve dictionary representation if there are too many |
| 4383 // descriptors. | 4392 // descriptors. |
| 4384 int number_of_elements = dictionary->NumberOfElements(); | 4393 int number_of_elements = dictionary->NumberOfElements(); |
| 4385 if (number_of_elements > kMaxNumberOfDescriptors) return; | 4394 if (number_of_elements > kMaxNumberOfDescriptors) return; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4407 number_of_fields += 1; | 4416 number_of_fields += 1; |
| 4408 } | 4417 } |
| 4409 } | 4418 } |
| 4410 | 4419 |
| 4411 int inobject_props = object->map()->inobject_properties(); | 4420 int inobject_props = object->map()->inobject_properties(); |
| 4412 | 4421 |
| 4413 // Allocate new map. | 4422 // Allocate new map. |
| 4414 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 4423 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 4415 new_map->set_dictionary_map(false); | 4424 new_map->set_dictionary_map(false); |
| 4416 | 4425 |
| 4426 #if TRACE_MAPS |
| 4427 if (FLAG_trace_maps) { |
| 4428 PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", |
| 4429 reinterpret_cast<void*>(object->map()), |
| 4430 reinterpret_cast<void*>(*new_map), reason); |
| 4431 } |
| 4432 #endif |
| 4433 |
| 4417 if (instance_descriptor_length == 0) { | 4434 if (instance_descriptor_length == 0) { |
| 4418 DisallowHeapAllocation no_gc; | 4435 DisallowHeapAllocation no_gc; |
| 4419 DCHECK_LE(unused_property_fields, inobject_props); | 4436 DCHECK_LE(unused_property_fields, inobject_props); |
| 4420 // Transform the object. | 4437 // Transform the object. |
| 4421 new_map->set_unused_property_fields(inobject_props); | 4438 new_map->set_unused_property_fields(inobject_props); |
| 4422 object->synchronized_set_map(*new_map); | 4439 object->synchronized_set_map(*new_map); |
| 4423 object->set_properties(isolate->heap()->empty_fixed_array()); | 4440 object->set_properties(isolate->heap()->empty_fixed_array()); |
| 4424 // Check that it really works. | 4441 // Check that it really works. |
| 4425 DCHECK(object->HasFastProperties()); | 4442 DCHECK(object->HasFastProperties()); |
| 4426 return; | 4443 return; |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5067 PropertyNormalizationMode mode = object->map()->is_prototype_map() | 5084 PropertyNormalizationMode mode = object->map()->is_prototype_map() |
| 5068 ? KEEP_INOBJECT_PROPERTIES | 5085 ? KEEP_INOBJECT_PROPERTIES |
| 5069 : CLEAR_INOBJECT_PROPERTIES; | 5086 : CLEAR_INOBJECT_PROPERTIES; |
| 5070 Handle<JSObject> holder = it.GetHolder<JSObject>(); | 5087 Handle<JSObject> holder = it.GetHolder<JSObject>(); |
| 5071 // TODO(verwaest): Remove this temporary compatibility hack when blink | 5088 // TODO(verwaest): Remove this temporary compatibility hack when blink |
| 5072 // tests are updated. | 5089 // tests are updated. |
| 5073 if (!holder.is_identical_to(object) && | 5090 if (!holder.is_identical_to(object) && |
| 5074 !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) { | 5091 !(object->IsJSGlobalProxy() && holder->IsJSGlobalObject())) { |
| 5075 return it.isolate()->factory()->true_value(); | 5092 return it.isolate()->factory()->true_value(); |
| 5076 } | 5093 } |
| 5077 NormalizeProperties(holder, mode, 0); | 5094 NormalizeProperties(holder, mode, 0, "DeletingProperty"); |
| 5078 Handle<Object> result = | 5095 Handle<Object> result = |
| 5079 DeleteNormalizedProperty(holder, name, delete_mode); | 5096 DeleteNormalizedProperty(holder, name, delete_mode); |
| 5080 ReoptimizeIfPrototype(holder); | 5097 ReoptimizeIfPrototype(holder); |
| 5081 | 5098 |
| 5082 if (is_observed) { | 5099 if (is_observed) { |
| 5083 RETURN_ON_EXCEPTION( | 5100 RETURN_ON_EXCEPTION( |
| 5084 it.isolate(), | 5101 it.isolate(), |
| 5085 EnqueueChangeRecord(object, "delete", name, old_value), Object); | 5102 EnqueueChangeRecord(object, "delete", name, old_value), Object); |
| 5086 } | 5103 } |
| 5087 | 5104 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5285 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 5302 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 5286 DCHECK(object->HasDictionaryElements() || | 5303 DCHECK(object->HasDictionaryElements() || |
| 5287 object->HasDictionaryArgumentsElements()); | 5304 object->HasDictionaryArgumentsElements()); |
| 5288 | 5305 |
| 5289 // Make sure that we never go back to fast case. | 5306 // Make sure that we never go back to fast case. |
| 5290 dictionary->set_requires_slow_elements(); | 5307 dictionary->set_requires_slow_elements(); |
| 5291 | 5308 |
| 5292 // Do a map transition, other objects with this map may still | 5309 // Do a map transition, other objects with this map may still |
| 5293 // be extensible. | 5310 // be extensible. |
| 5294 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5311 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5295 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5312 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); |
| 5296 | 5313 |
| 5297 new_map->set_is_extensible(false); | 5314 new_map->set_is_extensible(false); |
| 5298 JSObject::MigrateToMap(object, new_map); | 5315 JSObject::MigrateToMap(object, new_map); |
| 5299 DCHECK(!object->map()->is_extensible()); | 5316 DCHECK(!object->map()->is_extensible()); |
| 5300 | 5317 |
| 5301 if (object->map()->is_observed()) { | 5318 if (object->map()->is_observed()) { |
| 5302 RETURN_ON_EXCEPTION( | 5319 RETURN_ON_EXCEPTION( |
| 5303 isolate, | 5320 isolate, |
| 5304 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), | 5321 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), |
| 5305 isolate->factory()->the_hole_value()), | 5322 isolate->factory()->the_hole_value()), |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5397 DCHECK(transition_map->is_frozen()); | 5414 DCHECK(transition_map->is_frozen()); |
| 5398 DCHECK(!transition_map->is_extensible()); | 5415 DCHECK(!transition_map->is_extensible()); |
| 5399 JSObject::MigrateToMap(object, transition_map); | 5416 JSObject::MigrateToMap(object, transition_map); |
| 5400 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5417 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
| 5401 // Create a new descriptor array with fully-frozen properties | 5418 // Create a new descriptor array with fully-frozen properties |
| 5402 Handle<Map> new_map = Map::CopyForFreeze(old_map); | 5419 Handle<Map> new_map = Map::CopyForFreeze(old_map); |
| 5403 JSObject::MigrateToMap(object, new_map); | 5420 JSObject::MigrateToMap(object, new_map); |
| 5404 } else { | 5421 } else { |
| 5405 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); | 5422 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); |
| 5406 // Slow path: need to normalize properties for safety | 5423 // Slow path: need to normalize properties for safety |
| 5407 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5424 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "SlowFreeze"); |
| 5408 | 5425 |
| 5409 // Create a new map, since other objects with this map may be extensible. | 5426 // Create a new map, since other objects with this map may be extensible. |
| 5410 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5427 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5411 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5428 Handle<Map> new_map = Map::Copy(handle(object->map()), "SlowCopyForFreeze"); |
| 5412 new_map->freeze(); | 5429 new_map->freeze(); |
| 5413 new_map->set_is_extensible(false); | 5430 new_map->set_is_extensible(false); |
| 5414 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5431 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5415 JSObject::MigrateToMap(object, new_map); | 5432 JSObject::MigrateToMap(object, new_map); |
| 5416 | 5433 |
| 5417 // Freeze dictionary-mode properties | 5434 // Freeze dictionary-mode properties |
| 5418 FreezeDictionary(object->property_dictionary()); | 5435 FreezeDictionary(object->property_dictionary()); |
| 5419 } | 5436 } |
| 5420 | 5437 |
| 5421 DCHECK(object->map()->has_dictionary_elements()); | 5438 DCHECK(object->map()->has_dictionary_elements()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 5443 Handle<Map> old_map(object->map(), isolate); | 5460 Handle<Map> old_map(object->map(), isolate); |
| 5444 DCHECK(!old_map->is_observed()); | 5461 DCHECK(!old_map->is_observed()); |
| 5445 int transition_index = | 5462 int transition_index = |
| 5446 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); | 5463 old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); |
| 5447 if (transition_index != TransitionArray::kNotFound) { | 5464 if (transition_index != TransitionArray::kNotFound) { |
| 5448 new_map = handle(old_map->GetTransition(transition_index), isolate); | 5465 new_map = handle(old_map->GetTransition(transition_index), isolate); |
| 5449 DCHECK(new_map->is_observed()); | 5466 DCHECK(new_map->is_observed()); |
| 5450 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5467 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
| 5451 new_map = Map::CopyForObserved(old_map); | 5468 new_map = Map::CopyForObserved(old_map); |
| 5452 } else { | 5469 } else { |
| 5453 new_map = Map::Copy(old_map); | 5470 new_map = Map::Copy(old_map, "SlowObserved"); |
| 5454 new_map->set_is_observed(); | 5471 new_map->set_is_observed(); |
| 5455 } | 5472 } |
| 5456 JSObject::MigrateToMap(object, new_map); | 5473 JSObject::MigrateToMap(object, new_map); |
| 5457 } | 5474 } |
| 5458 | 5475 |
| 5459 | 5476 |
| 5460 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, | 5477 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object, |
| 5461 Representation representation, | 5478 Representation representation, |
| 5462 FieldIndex index) { | 5479 FieldIndex index) { |
| 5463 Isolate* isolate = object->GetIsolate(); | 5480 Isolate* isolate = object->GetIsolate(); |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6160 | 6177 |
| 6161 | 6178 |
| 6162 void JSObject::SetPropertyCallback(Handle<JSObject> object, | 6179 void JSObject::SetPropertyCallback(Handle<JSObject> object, |
| 6163 Handle<Name> name, | 6180 Handle<Name> name, |
| 6164 Handle<Object> structure, | 6181 Handle<Object> structure, |
| 6165 PropertyAttributes attributes) { | 6182 PropertyAttributes attributes) { |
| 6166 PropertyNormalizationMode mode = object->map()->is_prototype_map() | 6183 PropertyNormalizationMode mode = object->map()->is_prototype_map() |
| 6167 ? KEEP_INOBJECT_PROPERTIES | 6184 ? KEEP_INOBJECT_PROPERTIES |
| 6168 : CLEAR_INOBJECT_PROPERTIES; | 6185 : CLEAR_INOBJECT_PROPERTIES; |
| 6169 // Normalize object to make this operation simple. | 6186 // Normalize object to make this operation simple. |
| 6170 NormalizeProperties(object, mode, 0); | 6187 NormalizeProperties(object, mode, 0, "SetPropertyCallback"); |
| 6171 | 6188 |
| 6172 // For the global object allocate a new map to invalidate the global inline | 6189 // For the global object allocate a new map to invalidate the global inline |
| 6173 // caches which have a global property cell reference directly in the code. | 6190 // caches which have a global property cell reference directly in the code. |
| 6174 if (object->IsGlobalObject()) { | 6191 if (object->IsGlobalObject()) { |
| 6175 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 6192 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 6176 DCHECK(new_map->is_dictionary_map()); | 6193 DCHECK(new_map->is_dictionary_map()); |
| 6194 #if TRACE_MAPS |
| 6195 if (FLAG_trace_maps) { |
| 6196 PrintF("[TraceMaps: GlobalPropertyCallback from= %p to= %p ]\n", |
| 6197 reinterpret_cast<void*>(object->map()), |
| 6198 reinterpret_cast<void*>(*new_map)); |
| 6199 } |
| 6200 #endif |
| 6177 JSObject::MigrateToMap(object, new_map); | 6201 JSObject::MigrateToMap(object, new_map); |
| 6178 | 6202 |
| 6179 // When running crankshaft, changing the map is not enough. We | 6203 // When running crankshaft, changing the map is not enough. We |
| 6180 // need to deoptimize all functions that rely on this global | 6204 // need to deoptimize all functions that rely on this global |
| 6181 // object. | 6205 // object. |
| 6182 Deoptimizer::DeoptimizeGlobalObject(*object); | 6206 Deoptimizer::DeoptimizeGlobalObject(*object); |
| 6183 } | 6207 } |
| 6184 | 6208 |
| 6185 // Update the dictionary with the new CALLBACKS property. | 6209 // Update the dictionary with the new CALLBACKS property. |
| 6186 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6210 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6487 if (!map->is_dictionary_map()) { | 6511 if (!map->is_dictionary_map()) { |
| 6488 new_bit_field3 = IsUnstable::update(new_bit_field3, false); | 6512 new_bit_field3 = IsUnstable::update(new_bit_field3, false); |
| 6489 } | 6513 } |
| 6490 new_bit_field3 = ConstructionCount::update(new_bit_field3, | 6514 new_bit_field3 = ConstructionCount::update(new_bit_field3, |
| 6491 JSFunction::kNoSlackTracking); | 6515 JSFunction::kNoSlackTracking); |
| 6492 result->set_bit_field3(new_bit_field3); | 6516 result->set_bit_field3(new_bit_field3); |
| 6493 return result; | 6517 return result; |
| 6494 } | 6518 } |
| 6495 | 6519 |
| 6496 | 6520 |
| 6497 Handle<Map> Map::Normalize(Handle<Map> fast_map, | 6521 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode, |
| 6498 PropertyNormalizationMode mode) { | 6522 const char* reason) { |
| 6499 DCHECK(!fast_map->is_dictionary_map()); | 6523 DCHECK(!fast_map->is_dictionary_map()); |
| 6500 | 6524 |
| 6501 Isolate* isolate = fast_map->GetIsolate(); | 6525 Isolate* isolate = fast_map->GetIsolate(); |
| 6502 Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(), | 6526 Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(), |
| 6503 isolate); | 6527 isolate); |
| 6504 bool use_cache = !maybe_cache->IsUndefined(); | 6528 bool use_cache = !maybe_cache->IsUndefined(); |
| 6505 Handle<NormalizedMapCache> cache; | 6529 Handle<NormalizedMapCache> cache; |
| 6506 if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache); | 6530 if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache); |
| 6507 | 6531 |
| 6508 Handle<Map> new_map; | 6532 Handle<Map> new_map; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 6527 new_map->address() + offset, | 6551 new_map->address() + offset, |
| 6528 Map::kSize - offset) == 0); | 6552 Map::kSize - offset) == 0); |
| 6529 } | 6553 } |
| 6530 #endif | 6554 #endif |
| 6531 } else { | 6555 } else { |
| 6532 new_map = Map::CopyNormalized(fast_map, mode); | 6556 new_map = Map::CopyNormalized(fast_map, mode); |
| 6533 if (use_cache) { | 6557 if (use_cache) { |
| 6534 cache->Set(fast_map, new_map); | 6558 cache->Set(fast_map, new_map); |
| 6535 isolate->counters()->normalized_maps()->Increment(); | 6559 isolate->counters()->normalized_maps()->Increment(); |
| 6536 } | 6560 } |
| 6561 #if TRACE_MAPS |
| 6562 if (FLAG_trace_maps) { |
| 6563 PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n", |
| 6564 reinterpret_cast<void*>(*fast_map), |
| 6565 reinterpret_cast<void*>(*new_map), reason); |
| 6566 } |
| 6567 #endif |
| 6537 } | 6568 } |
| 6538 fast_map->NotifyLeafMapLayoutChange(); | 6569 fast_map->NotifyLeafMapLayoutChange(); |
| 6539 return new_map; | 6570 return new_map; |
| 6540 } | 6571 } |
| 6541 | 6572 |
| 6542 | 6573 |
| 6543 Handle<Map> Map::CopyNormalized(Handle<Map> map, | 6574 Handle<Map> Map::CopyNormalized(Handle<Map> map, |
| 6544 PropertyNormalizationMode mode) { | 6575 PropertyNormalizationMode mode) { |
| 6545 int new_instance_size = map->instance_size(); | 6576 int new_instance_size = map->instance_size(); |
| 6546 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 6577 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6609 result->InitializeDescriptors(*descriptors); | 6640 result->InitializeDescriptors(*descriptors); |
| 6610 } | 6641 } |
| 6611 | 6642 |
| 6612 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); | 6643 DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
| 6613 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); | 6644 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
| 6614 | 6645 |
| 6615 return result; | 6646 return result; |
| 6616 } | 6647 } |
| 6617 | 6648 |
| 6618 | 6649 |
| 6650 #if TRACE_MAPS |
| 6651 |
| 6652 // static |
| 6653 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) { |
| 6654 if (FLAG_trace_maps) { |
| 6655 PrintF("[TraceMaps: %s from= %p to= %p name= ", what, |
| 6656 reinterpret_cast<void*>(from), reinterpret_cast<void*>(to)); |
| 6657 name->NameShortPrint(); |
| 6658 PrintF(" ]\n"); |
| 6659 } |
| 6660 } |
| 6661 |
| 6662 |
| 6663 // static |
| 6664 void Map::TraceAllTransitions(Map* map) { |
| 6665 if (!map->HasTransitionArray()) return; |
| 6666 TransitionArray* transitions = map->transitions(); |
| 6667 for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
| 6668 Map* target = transitions->GetTarget(i); |
| 6669 Map::TraceTransition("Transition", map, target, transitions->GetKey(i)); |
| 6670 Map::TraceAllTransitions(target); |
| 6671 } |
| 6672 } |
| 6673 |
| 6674 #endif // TRACE_MAPS |
| 6675 |
| 6676 |
| 6619 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | 6677 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
| 6620 Handle<Name> name, SimpleTransitionFlag flag) { | 6678 Handle<Name> name, SimpleTransitionFlag flag) { |
| 6621 parent->set_owns_descriptors(false); | 6679 parent->set_owns_descriptors(false); |
| 6622 if (parent->is_prototype_map()) { | 6680 if (parent->is_prototype_map()) { |
| 6623 DCHECK(child->is_prototype_map()); | 6681 DCHECK(child->is_prototype_map()); |
| 6682 #if TRACE_MAPS |
| 6683 Map::TraceTransition("NoTransition", *parent, *child, *name); |
| 6684 #endif |
| 6624 } else { | 6685 } else { |
| 6625 Handle<TransitionArray> transitions = | 6686 Handle<TransitionArray> transitions = |
| 6626 TransitionArray::Insert(parent, name, child, flag); | 6687 TransitionArray::Insert(parent, name, child, flag); |
| 6627 if (!parent->HasTransitionArray() || | 6688 if (!parent->HasTransitionArray() || |
| 6628 *transitions != parent->transitions()) { | 6689 *transitions != parent->transitions()) { |
| 6629 parent->set_transitions(*transitions); | 6690 parent->set_transitions(*transitions); |
| 6630 } | 6691 } |
| 6631 child->SetBackPointer(*parent); | 6692 child->SetBackPointer(*parent); |
| 6693 #if TRACE_MAPS |
| 6694 Map::TraceTransition("Transition", *parent, *child, *name); |
| 6695 #endif |
| 6632 } | 6696 } |
| 6633 } | 6697 } |
| 6634 | 6698 |
| 6635 | 6699 |
| 6636 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, | 6700 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
| 6637 Handle<DescriptorArray> descriptors, | 6701 Handle<DescriptorArray> descriptors, |
| 6638 TransitionFlag flag, | 6702 TransitionFlag flag, |
| 6639 MaybeHandle<Name> maybe_name, | 6703 MaybeHandle<Name> maybe_name, |
| 6704 const char* reason, |
| 6640 SimpleTransitionFlag simple_flag) { | 6705 SimpleTransitionFlag simple_flag) { |
| 6641 DCHECK(descriptors->IsSortedNoDuplicates()); | 6706 DCHECK(descriptors->IsSortedNoDuplicates()); |
| 6642 | 6707 |
| 6643 Handle<Map> result = CopyDropDescriptors(map); | 6708 Handle<Map> result = CopyDropDescriptors(map); |
| 6644 result->InitializeDescriptors(*descriptors); | 6709 result->InitializeDescriptors(*descriptors); |
| 6645 | 6710 |
| 6646 if (!map->is_prototype_map()) { | 6711 if (!map->is_prototype_map()) { |
| 6647 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 6712 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
| 6648 Handle<Name> name; | 6713 Handle<Name> name; |
| 6649 CHECK(maybe_name.ToHandle(&name)); | 6714 CHECK(maybe_name.ToHandle(&name)); |
| 6650 ConnectTransition(map, result, name, simple_flag); | 6715 ConnectTransition(map, result, name, simple_flag); |
| 6651 } else { | 6716 } else { |
| 6652 int length = descriptors->number_of_descriptors(); | 6717 int length = descriptors->number_of_descriptors(); |
| 6653 for (int i = 0; i < length; i++) { | 6718 for (int i = 0; i < length; i++) { |
| 6654 descriptors->SetRepresentation(i, Representation::Tagged()); | 6719 descriptors->SetRepresentation(i, Representation::Tagged()); |
| 6655 if (descriptors->GetDetails(i).type() == FIELD) { | 6720 if (descriptors->GetDetails(i).type() == FIELD) { |
| 6656 descriptors->SetValue(i, HeapType::Any()); | 6721 descriptors->SetValue(i, HeapType::Any()); |
| 6657 } | 6722 } |
| 6658 } | 6723 } |
| 6659 } | 6724 } |
| 6660 } | 6725 } |
| 6726 #if TRACE_MAPS |
| 6727 if (FLAG_trace_maps && |
| 6728 // Mirror conditions above that did not call ConnectTransition(). |
| 6729 (map->is_prototype_map() || |
| 6730 !(flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()))) { |
| 6731 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", |
| 6732 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), |
| 6733 reason); |
| 6734 } |
| 6735 #endif |
| 6661 | 6736 |
| 6662 return result; | 6737 return result; |
| 6663 } | 6738 } |
| 6664 | 6739 |
| 6665 | 6740 |
| 6666 // Since this method is used to rewrite an existing transition tree, it can | 6741 // Since this method is used to rewrite an existing transition tree, it can |
| 6667 // always insert transitions without checking. | 6742 // always insert transitions without checking. |
| 6668 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | 6743 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 6669 int new_descriptor, | 6744 int new_descriptor, |
| 6670 Handle<DescriptorArray> descriptors) { | 6745 Handle<DescriptorArray> descriptors) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6719 ConnectElementsTransition(map, new_map); | 6794 ConnectElementsTransition(map, new_map); |
| 6720 | 6795 |
| 6721 new_map->set_elements_kind(kind); | 6796 new_map->set_elements_kind(kind); |
| 6722 new_map->InitializeDescriptors(map->instance_descriptors()); | 6797 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6723 return new_map; | 6798 return new_map; |
| 6724 } | 6799 } |
| 6725 | 6800 |
| 6726 // In case the map did not own its own descriptors, a split is forced by | 6801 // In case the map did not own its own descriptors, a split is forced by |
| 6727 // copying the map; creating a new descriptor array cell. | 6802 // copying the map; creating a new descriptor array cell. |
| 6728 // Create a new free-floating map only if we are not allowed to store it. | 6803 // Create a new free-floating map only if we are not allowed to store it. |
| 6729 Handle<Map> new_map = Copy(map); | 6804 Handle<Map> new_map = Copy(map, "CopyAsElementsKind"); |
| 6730 | 6805 |
| 6731 new_map->set_elements_kind(kind); | 6806 new_map->set_elements_kind(kind); |
| 6732 | 6807 |
| 6733 if (insert_transition) { | 6808 if (insert_transition) { |
| 6734 ConnectElementsTransition(map, new_map); | 6809 ConnectElementsTransition(map, new_map); |
| 6735 } | 6810 } |
| 6736 | 6811 |
| 6737 return new_map; | 6812 return new_map; |
| 6738 } | 6813 } |
| 6739 | 6814 |
| 6740 | 6815 |
| 6741 Handle<Map> Map::CopyForObserved(Handle<Map> map) { | 6816 Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
| 6742 DCHECK(!map->is_observed()); | 6817 DCHECK(!map->is_observed()); |
| 6743 | 6818 |
| 6744 Isolate* isolate = map->GetIsolate(); | 6819 Isolate* isolate = map->GetIsolate(); |
| 6745 | 6820 |
| 6746 // In case the map owned its own descriptors, share the descriptors and | 6821 // In case the map owned its own descriptors, share the descriptors and |
| 6747 // transfer ownership to the new map. | 6822 // transfer ownership to the new map. |
| 6748 Handle<Map> new_map; | 6823 Handle<Map> new_map; |
| 6749 if (map->owns_descriptors()) { | 6824 if (map->owns_descriptors()) { |
| 6750 new_map = CopyDropDescriptors(map); | 6825 new_map = CopyDropDescriptors(map); |
| 6751 } else { | 6826 } else { |
| 6752 DCHECK(!map->is_prototype_map()); | 6827 DCHECK(!map->is_prototype_map()); |
| 6753 new_map = Copy(map); | 6828 new_map = Copy(map, "CopyForObserved"); |
| 6754 } | 6829 } |
| 6755 | 6830 |
| 6756 new_map->set_is_observed(); | 6831 new_map->set_is_observed(); |
| 6757 if (map->owns_descriptors()) { | 6832 if (map->owns_descriptors()) { |
| 6758 new_map->InitializeDescriptors(map->instance_descriptors()); | 6833 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6759 } | 6834 } |
| 6760 | 6835 |
| 6761 if (map->CanHaveMoreTransitions()) { | 6836 if (map->CanHaveMoreTransitions()) { |
| 6762 Handle<Name> name = isolate->factory()->observed_symbol(); | 6837 Handle<Name> name = isolate->factory()->observed_symbol(); |
| 6763 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); | 6838 ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); |
| 6764 } | 6839 } |
| 6765 return new_map; | 6840 return new_map; |
| 6766 } | 6841 } |
| 6767 | 6842 |
| 6768 | 6843 |
| 6769 Handle<Map> Map::Copy(Handle<Map> map) { | 6844 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) { |
| 6770 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 6845 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 6771 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6846 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 6772 Handle<DescriptorArray> new_descriptors = | 6847 Handle<DescriptorArray> new_descriptors = |
| 6773 DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors); | 6848 DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors); |
| 6774 return CopyReplaceDescriptors(map, new_descriptors, OMIT_TRANSITION, | 6849 return CopyReplaceDescriptors(map, new_descriptors, OMIT_TRANSITION, |
| 6775 MaybeHandle<Name>(), SPECIAL_TRANSITION); | 6850 MaybeHandle<Name>(), reason, |
| 6851 SPECIAL_TRANSITION); |
| 6776 } | 6852 } |
| 6777 | 6853 |
| 6778 | 6854 |
| 6779 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { | 6855 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { |
| 6780 Handle<Map> copy = Copy(handle(isolate->object_function()->initial_map())); | 6856 Handle<Map> copy = |
| 6857 Copy(handle(isolate->object_function()->initial_map()), "MapCreate"); |
| 6781 | 6858 |
| 6782 // Check that we do not overflow the instance size when adding the extra | 6859 // Check that we do not overflow the instance size when adding the extra |
| 6783 // inobject properties. If the instance size overflows, we allocate as many | 6860 // inobject properties. If the instance size overflows, we allocate as many |
| 6784 // properties as we can as inobject properties. | 6861 // properties as we can as inobject properties. |
| 6785 int max_extra_properties = | 6862 int max_extra_properties = |
| 6786 (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2; | 6863 (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2; |
| 6787 | 6864 |
| 6788 if (inobject_properties > max_extra_properties) { | 6865 if (inobject_properties > max_extra_properties) { |
| 6789 inobject_properties = max_extra_properties; | 6866 inobject_properties = max_extra_properties; |
| 6790 } | 6867 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 6801 } | 6878 } |
| 6802 | 6879 |
| 6803 | 6880 |
| 6804 Handle<Map> Map::CopyForFreeze(Handle<Map> map) { | 6881 Handle<Map> Map::CopyForFreeze(Handle<Map> map) { |
| 6805 int num_descriptors = map->NumberOfOwnDescriptors(); | 6882 int num_descriptors = map->NumberOfOwnDescriptors(); |
| 6806 Isolate* isolate = map->GetIsolate(); | 6883 Isolate* isolate = map->GetIsolate(); |
| 6807 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( | 6884 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( |
| 6808 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); | 6885 handle(map->instance_descriptors(), isolate), num_descriptors, FROZEN); |
| 6809 Handle<Map> new_map = CopyReplaceDescriptors( | 6886 Handle<Map> new_map = CopyReplaceDescriptors( |
| 6810 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol(), | 6887 map, new_desc, INSERT_TRANSITION, isolate->factory()->frozen_symbol(), |
| 6811 SPECIAL_TRANSITION); | 6888 "CopyForFreeze", SPECIAL_TRANSITION); |
| 6812 new_map->freeze(); | 6889 new_map->freeze(); |
| 6813 new_map->set_is_extensible(false); | 6890 new_map->set_is_extensible(false); |
| 6814 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 6891 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 6815 return new_map; | 6892 return new_map; |
| 6816 } | 6893 } |
| 6817 | 6894 |
| 6818 | 6895 |
| 6819 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { | 6896 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { |
| 6820 PropertyDetails details = GetDetails(descriptor); | 6897 PropertyDetails details = GetDetails(descriptor); |
| 6821 switch (details.type()) { | 6898 switch (details.type()) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6891 } else if (!map->TooManyFastProperties(store_mode)) { | 6968 } else if (!map->TooManyFastProperties(store_mode)) { |
| 6892 Isolate* isolate = name->GetIsolate(); | 6969 Isolate* isolate = name->GetIsolate(); |
| 6893 Representation representation = value->OptimalRepresentation(); | 6970 Representation representation = value->OptimalRepresentation(); |
| 6894 Handle<HeapType> type = value->OptimalType(isolate, representation); | 6971 Handle<HeapType> type = value->OptimalType(isolate, representation); |
| 6895 maybe_map = | 6972 maybe_map = |
| 6896 Map::CopyWithField(map, name, type, attributes, representation, flag); | 6973 Map::CopyWithField(map, name, type, attributes, representation, flag); |
| 6897 } | 6974 } |
| 6898 | 6975 |
| 6899 Handle<Map> result; | 6976 Handle<Map> result; |
| 6900 if (!maybe_map.ToHandle(&result)) { | 6977 if (!maybe_map.ToHandle(&result)) { |
| 6901 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); | 6978 #if TRACE_MAPS |
| 6979 if (FLAG_trace_maps) { |
| 6980 Vector<char> name_buffer = Vector<char>::New(100); |
| 6981 name->NameShortPrint(name_buffer); |
| 6982 Vector<char> buffer = Vector<char>::New(128); |
| 6983 SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start()); |
| 6984 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start()); |
| 6985 } |
| 6986 #endif |
| 6987 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, |
| 6988 "TooManyFastProperties"); |
| 6902 } | 6989 } |
| 6903 | 6990 |
| 6904 return result; | 6991 return result; |
| 6905 } | 6992 } |
| 6906 | 6993 |
| 6907 | 6994 |
| 6908 Handle<Map> Map::ReconfigureDataProperty(Handle<Map> map, int descriptor, | 6995 Handle<Map> Map::ReconfigureDataProperty(Handle<Map> map, int descriptor, |
| 6909 PropertyAttributes attributes) { | 6996 PropertyAttributes attributes) { |
| 6910 // Dictionaries have to be reconfigured in-place. | 6997 // Dictionaries have to be reconfigured in-place. |
| 6911 DCHECK(!map->is_dictionary_map()); | 6998 DCHECK(!map->is_dictionary_map()); |
| 6912 | 6999 |
| 6913 // For now, give up on transitioning and just create a unique map. | 7000 // For now, give up on transitioning and just create a unique map. |
| 6914 // TODO(verwaest/ishell): Cache transitions with different attributes. | 7001 // TODO(verwaest/ishell): Cache transitions with different attributes. |
| 6915 return CopyGeneralizeAllRepresentations(map, descriptor, FORCE_FIELD, | 7002 return CopyGeneralizeAllRepresentations( |
| 6916 attributes, "attributes mismatch"); | 7003 map, descriptor, FORCE_FIELD, attributes, "GenAll_AttributesMismatch"); |
| 6917 } | 7004 } |
| 6918 | 7005 |
| 6919 | 7006 |
| 6920 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, | 7007 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, |
| 6921 Handle<Name> name, | 7008 Handle<Name> name, |
| 6922 AccessorComponent component, | 7009 AccessorComponent component, |
| 6923 Handle<Object> accessor, | 7010 Handle<Object> accessor, |
| 6924 PropertyAttributes attributes) { | 7011 PropertyAttributes attributes) { |
| 6925 Isolate* isolate = name->GetIsolate(); | 7012 Isolate* isolate = name->GetIsolate(); |
| 6926 | 7013 |
| 6927 // Dictionary maps can always have additional data properties. | 7014 // Dictionary maps can always have additional data properties. |
| 6928 if (map->is_dictionary_map()) { | 7015 if (map->is_dictionary_map()) { |
| 6929 // For global objects, property cells are inlined. We need to change the | 7016 // For global objects, property cells are inlined. We need to change the |
| 6930 // map. | 7017 // map. |
| 6931 if (map->IsGlobalObjectMap()) return Copy(map); | 7018 if (map->IsGlobalObjectMap()) return Copy(map, "GlobalAccessor"); |
| 6932 return map; | 7019 return map; |
| 6933 } | 7020 } |
| 6934 | 7021 |
| 6935 // Migrate to the newest map before transitioning to the new property. | 7022 // Migrate to the newest map before transitioning to the new property. |
| 6936 map = Update(map); | 7023 map = Update(map); |
| 6937 | 7024 |
| 6938 PropertyNormalizationMode mode = map->is_prototype_map() | 7025 PropertyNormalizationMode mode = map->is_prototype_map() |
| 6939 ? KEEP_INOBJECT_PROPERTIES | 7026 ? KEEP_INOBJECT_PROPERTIES |
| 6940 : CLEAR_INOBJECT_PROPERTIES; | 7027 : CLEAR_INOBJECT_PROPERTIES; |
| 6941 | 7028 |
| 6942 int index = map->SearchTransition(CALLBACKS, *name, attributes); | 7029 int index = map->SearchTransition(CALLBACKS, *name, attributes); |
| 6943 if (index != TransitionArray::kNotFound) { | 7030 if (index != TransitionArray::kNotFound) { |
| 6944 Handle<Map> transition(map->GetTransition(index)); | 7031 Handle<Map> transition(map->GetTransition(index)); |
| 6945 DescriptorArray* descriptors = transition->instance_descriptors(); | 7032 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 6946 int descriptor = transition->LastAdded(); | 7033 int descriptor = transition->LastAdded(); |
| 6947 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); | 7034 DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); |
| 6948 | 7035 |
| 6949 DCHECK_EQ(CALLBACKS, descriptors->GetDetails(descriptor).type()); | 7036 DCHECK_EQ(CALLBACKS, descriptors->GetDetails(descriptor).type()); |
| 6950 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); | 7037 DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); |
| 6951 | 7038 |
| 6952 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); | 7039 Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); |
| 6953 if (!maybe_pair->IsAccessorPair()) { | 7040 if (!maybe_pair->IsAccessorPair()) { |
| 6954 return Map::Normalize(map, mode); | 7041 return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); |
| 6955 } | 7042 } |
| 6956 | 7043 |
| 6957 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair); | 7044 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair); |
| 6958 if (pair->get(component) != *accessor) { | 7045 if (pair->get(component) != *accessor) { |
| 6959 return Map::Normalize(map, mode); | 7046 return Map::Normalize(map, mode, "TransitionToDifferentAccessor"); |
| 6960 } | 7047 } |
| 6961 | 7048 |
| 6962 return transition; | 7049 return transition; |
| 6963 } | 7050 } |
| 6964 | 7051 |
| 6965 Handle<AccessorPair> pair; | 7052 Handle<AccessorPair> pair; |
| 6966 DescriptorArray* old_descriptors = map->instance_descriptors(); | 7053 DescriptorArray* old_descriptors = map->instance_descriptors(); |
| 6967 int descriptor = old_descriptors->SearchWithCache(*name, *map); | 7054 int descriptor = old_descriptors->SearchWithCache(*name, *map); |
| 6968 if (descriptor != DescriptorArray::kNotFound) { | 7055 if (descriptor != DescriptorArray::kNotFound) { |
| 6969 if (descriptor != map->LastAdded()) { | 7056 if (descriptor != map->LastAdded()) { |
| 6970 return Map::Normalize(map, mode); | 7057 return Map::Normalize(map, mode, "AccessorsOverwritingNonLast"); |
| 6971 } | 7058 } |
| 6972 PropertyDetails old_details = old_descriptors->GetDetails(descriptor); | 7059 PropertyDetails old_details = old_descriptors->GetDetails(descriptor); |
| 6973 if (old_details.type() != CALLBACKS) { | 7060 if (old_details.type() != CALLBACKS) { |
| 6974 return Map::Normalize(map, mode); | 7061 return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors"); |
| 6975 } | 7062 } |
| 6976 | 7063 |
| 6977 if (old_details.attributes() != attributes) { | 7064 if (old_details.attributes() != attributes) { |
| 6978 return Map::Normalize(map, mode); | 7065 return Map::Normalize(map, mode, "AccessorsWithAttributes"); |
| 6979 } | 7066 } |
| 6980 | 7067 |
| 6981 Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate); | 7068 Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate); |
| 6982 if (!maybe_pair->IsAccessorPair()) { | 7069 if (!maybe_pair->IsAccessorPair()) { |
| 6983 return Map::Normalize(map, mode); | 7070 return Map::Normalize(map, mode, "AccessorsOverwritingNonPair"); |
| 6984 } | 7071 } |
| 6985 | 7072 |
| 6986 Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component); | 7073 Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component); |
| 6987 if (current == *accessor) return map; | 7074 if (current == *accessor) return map; |
| 6988 | 7075 |
| 6989 if (!current->IsTheHole()) { | 7076 if (!current->IsTheHole()) { |
| 6990 return Map::Normalize(map, mode); | 7077 return Map::Normalize(map, mode, "AccessorsOverwritingAccessors"); |
| 6991 } | 7078 } |
| 6992 | 7079 |
| 6993 pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair)); | 7080 pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair)); |
| 6994 } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors || | 7081 } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors || |
| 6995 map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) { | 7082 map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) { |
| 6996 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES); | 7083 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors"); |
| 6997 } else { | 7084 } else { |
| 6998 pair = isolate->factory()->NewAccessorPair(); | 7085 pair = isolate->factory()->NewAccessorPair(); |
| 6999 } | 7086 } |
| 7000 | 7087 |
| 7001 pair->set(component, *accessor); | 7088 pair->set(component, *accessor); |
| 7002 TransitionFlag flag = INSERT_TRANSITION; | 7089 TransitionFlag flag = INSERT_TRANSITION; |
| 7003 CallbacksDescriptor new_desc(name, pair, attributes); | 7090 CallbacksDescriptor new_desc(name, pair, attributes); |
| 7004 return Map::CopyInsertDescriptor(map, &new_desc, flag); | 7091 return Map::CopyInsertDescriptor(map, &new_desc, flag); |
| 7005 } | 7092 } |
| 7006 | 7093 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7017 map->owns_descriptors() && | 7104 map->owns_descriptors() && |
| 7018 map->CanHaveMoreTransitions()) { | 7105 map->CanHaveMoreTransitions()) { |
| 7019 return ShareDescriptor(map, descriptors, descriptor); | 7106 return ShareDescriptor(map, descriptors, descriptor); |
| 7020 } | 7107 } |
| 7021 | 7108 |
| 7022 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 7109 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
| 7023 descriptors, map->NumberOfOwnDescriptors(), 1); | 7110 descriptors, map->NumberOfOwnDescriptors(), 1); |
| 7024 new_descriptors->Append(descriptor); | 7111 new_descriptors->Append(descriptor); |
| 7025 | 7112 |
| 7026 return CopyReplaceDescriptors(map, new_descriptors, flag, | 7113 return CopyReplaceDescriptors(map, new_descriptors, flag, |
| 7027 descriptor->GetKey(), | 7114 descriptor->GetKey(), "CopyAddDescriptor", |
| 7028 SIMPLE_PROPERTY_TRANSITION); | 7115 SIMPLE_PROPERTY_TRANSITION); |
| 7029 } | 7116 } |
| 7030 | 7117 |
| 7031 | 7118 |
| 7032 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map, | 7119 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map, |
| 7033 Descriptor* descriptor, | 7120 Descriptor* descriptor, |
| 7034 TransitionFlag flag) { | 7121 TransitionFlag flag) { |
| 7035 Handle<DescriptorArray> old_descriptors(map->instance_descriptors()); | 7122 Handle<DescriptorArray> old_descriptors(map->instance_descriptors()); |
| 7036 | 7123 |
| 7037 // Ensure the key is unique. | 7124 // Ensure the key is unique. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7114 | 7201 |
| 7115 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( | 7202 Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
| 7116 descriptors, map->NumberOfOwnDescriptors()); | 7203 descriptors, map->NumberOfOwnDescriptors()); |
| 7117 | 7204 |
| 7118 new_descriptors->Replace(insertion_index, descriptor); | 7205 new_descriptors->Replace(insertion_index, descriptor); |
| 7119 | 7206 |
| 7120 SimpleTransitionFlag simple_flag = | 7207 SimpleTransitionFlag simple_flag = |
| 7121 (insertion_index == descriptors->number_of_descriptors() - 1) | 7208 (insertion_index == descriptors->number_of_descriptors() - 1) |
| 7122 ? SIMPLE_PROPERTY_TRANSITION | 7209 ? SIMPLE_PROPERTY_TRANSITION |
| 7123 : PROPERTY_TRANSITION; | 7210 : PROPERTY_TRANSITION; |
| 7124 return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag); | 7211 return CopyReplaceDescriptors(map, new_descriptors, flag, key, |
| 7212 "CopyReplaceDescriptor", simple_flag); |
| 7125 } | 7213 } |
| 7126 | 7214 |
| 7127 | 7215 |
| 7128 void Map::UpdateCodeCache(Handle<Map> map, | 7216 void Map::UpdateCodeCache(Handle<Map> map, |
| 7129 Handle<Name> name, | 7217 Handle<Name> name, |
| 7130 Handle<Code> code) { | 7218 Handle<Code> code) { |
| 7131 Isolate* isolate = map->GetIsolate(); | 7219 Isolate* isolate = map->GetIsolate(); |
| 7132 HandleScope scope(isolate); | 7220 HandleScope scope(isolate); |
| 7133 // Allocate the code cache if not present. | 7221 // Allocate the code cache if not present. |
| 7134 if (map->code_cache()->IsFixedArray()) { | 7222 if (map->code_cache()->IsFixedArray()) { |
| (...skipping 2272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9407 } | 9495 } |
| 9408 } | 9496 } |
| 9409 | 9497 |
| 9410 | 9498 |
| 9411 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, | 9499 void JSObject::OptimizeAsPrototype(Handle<JSObject> object, |
| 9412 PrototypeOptimizationMode mode) { | 9500 PrototypeOptimizationMode mode) { |
| 9413 if (object->IsGlobalObject()) return; | 9501 if (object->IsGlobalObject()) return; |
| 9414 if (object->IsJSGlobalProxy()) return; | 9502 if (object->IsJSGlobalProxy()) return; |
| 9415 if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) { | 9503 if (mode == FAST_PROTOTYPE && !object->map()->is_prototype_map()) { |
| 9416 // First normalize to ensure all JSFunctions are CONSTANT. | 9504 // First normalize to ensure all JSFunctions are CONSTANT. |
| 9417 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0); | 9505 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0, |
| 9506 "NormalizeAsPrototype"); |
| 9418 } | 9507 } |
| 9419 if (!object->HasFastProperties()) { | 9508 if (!object->HasFastProperties()) { |
| 9420 JSObject::MigrateSlowToFast(object, 0); | 9509 JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); |
| 9421 } | 9510 } |
| 9422 if (mode == FAST_PROTOTYPE && object->HasFastProperties() && | 9511 if (mode == FAST_PROTOTYPE && object->HasFastProperties() && |
| 9423 !object->map()->is_prototype_map()) { | 9512 !object->map()->is_prototype_map()) { |
| 9424 Handle<Map> new_map = Map::Copy(handle(object->map())); | 9513 Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype"); |
| 9425 JSObject::MigrateToMap(object, new_map); | 9514 JSObject::MigrateToMap(object, new_map); |
| 9426 object->map()->set_is_prototype_map(true); | 9515 object->map()->set_is_prototype_map(true); |
| 9427 } | 9516 } |
| 9428 } | 9517 } |
| 9429 | 9518 |
| 9430 | 9519 |
| 9431 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { | 9520 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) { |
| 9432 if (!object->map()->is_prototype_map()) return; | 9521 if (!object->map()->is_prototype_map()) return; |
| 9433 OptimizeAsPrototype(object, FAST_PROTOTYPE); | 9522 OptimizeAsPrototype(object, FAST_PROTOTYPE); |
| 9434 } | 9523 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9484 | 9573 |
| 9485 Handle<Map> initial_map(function->initial_map(), isolate); | 9574 Handle<Map> initial_map(function->initial_map(), isolate); |
| 9486 | 9575 |
| 9487 if (!initial_map->GetIsolate()->bootstrapper()->IsActive() && | 9576 if (!initial_map->GetIsolate()->bootstrapper()->IsActive() && |
| 9488 initial_map->instance_type() == JS_OBJECT_TYPE) { | 9577 initial_map->instance_type() == JS_OBJECT_TYPE) { |
| 9489 // Put the value in the initial map field until an initial map is needed. | 9578 // Put the value in the initial map field until an initial map is needed. |
| 9490 // At that point, a new initial map is created and the prototype is put | 9579 // At that point, a new initial map is created and the prototype is put |
| 9491 // into the initial map where it belongs. | 9580 // into the initial map where it belongs. |
| 9492 function->set_prototype_or_initial_map(*value); | 9581 function->set_prototype_or_initial_map(*value); |
| 9493 } else { | 9582 } else { |
| 9494 Handle<Map> new_map = Map::Copy(initial_map); | 9583 Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype"); |
| 9495 JSFunction::SetInitialMap(function, new_map, value); | 9584 JSFunction::SetInitialMap(function, new_map, value); |
| 9496 | 9585 |
| 9497 // If the function is used as the global Array function, cache the | 9586 // If the function is used as the global Array function, cache the |
| 9498 // initial map (and transitioned versions) in the native context. | 9587 // initial map (and transitioned versions) in the native context. |
| 9499 Context* native_context = function->context()->native_context(); | 9588 Context* native_context = function->context()->native_context(); |
| 9500 Object* array_function = | 9589 Object* array_function = |
| 9501 native_context->get(Context::ARRAY_FUNCTION_INDEX); | 9590 native_context->get(Context::ARRAY_FUNCTION_INDEX); |
| 9502 if (array_function->IsJSFunction() && | 9591 if (array_function->IsJSFunction() && |
| 9503 *function == JSFunction::cast(array_function)) { | 9592 *function == JSFunction::cast(array_function)) { |
| 9504 CacheInitialJSArrayMaps(handle(native_context, isolate), new_map); | 9593 CacheInitialJSArrayMaps(handle(native_context, isolate), new_map); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 9524 Handle<Object> construct_prototype = value; | 9613 Handle<Object> construct_prototype = value; |
| 9525 | 9614 |
| 9526 // If the value is not a JSReceiver, store the value in the map's | 9615 // If the value is not a JSReceiver, store the value in the map's |
| 9527 // constructor field so it can be accessed. Also, set the prototype | 9616 // constructor field so it can be accessed. Also, set the prototype |
| 9528 // used for constructing objects to the original object prototype. | 9617 // used for constructing objects to the original object prototype. |
| 9529 // See ECMA-262 13.2.2. | 9618 // See ECMA-262 13.2.2. |
| 9530 if (!value->IsJSReceiver()) { | 9619 if (!value->IsJSReceiver()) { |
| 9531 // Copy the map so this does not affect unrelated functions. | 9620 // Copy the map so this does not affect unrelated functions. |
| 9532 // Remove map transitions because they point to maps with a | 9621 // Remove map transitions because they point to maps with a |
| 9533 // different prototype. | 9622 // different prototype. |
| 9534 Handle<Map> new_map = Map::Copy(handle(function->map())); | 9623 Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype"); |
| 9535 | 9624 |
| 9536 JSObject::MigrateToMap(function, new_map); | 9625 JSObject::MigrateToMap(function, new_map); |
| 9537 new_map->set_constructor(*value); | 9626 new_map->set_constructor(*value); |
| 9538 new_map->set_non_instance_prototype(true); | 9627 new_map->set_non_instance_prototype(true); |
| 9539 Isolate* isolate = new_map->GetIsolate(); | 9628 Isolate* isolate = new_map->GetIsolate(); |
| 9540 construct_prototype = handle( | 9629 construct_prototype = handle( |
| 9541 isolate->context()->native_context()->initial_object_prototype(), | 9630 isolate->context()->native_context()->initial_object_prototype(), |
| 9542 isolate); | 9631 isolate); |
| 9543 } else { | 9632 } else { |
| 9544 function->map()->set_non_instance_prototype(false); | 9633 function->map()->set_non_instance_prototype(false); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 9572 | 9661 |
| 9573 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map, | 9662 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map, |
| 9574 Handle<Object> prototype) { | 9663 Handle<Object> prototype) { |
| 9575 if (prototype->IsJSObject()) { | 9664 if (prototype->IsJSObject()) { |
| 9576 Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype); | 9665 Handle<JSObject> js_proto = Handle<JSObject>::cast(prototype); |
| 9577 JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE); | 9666 JSObject::OptimizeAsPrototype(js_proto, FAST_PROTOTYPE); |
| 9578 } | 9667 } |
| 9579 map->set_prototype(*prototype); | 9668 map->set_prototype(*prototype); |
| 9580 function->set_prototype_or_initial_map(*map); | 9669 function->set_prototype_or_initial_map(*map); |
| 9581 map->set_constructor(*function); | 9670 map->set_constructor(*function); |
| 9671 #if TRACE_MAPS |
| 9672 if (FLAG_trace_maps) { |
| 9673 PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n", |
| 9674 reinterpret_cast<void*>(*map), function->shared()->unique_id(), |
| 9675 function->shared()->DebugName()->ToCString().get()); |
| 9676 } |
| 9677 #endif |
| 9582 } | 9678 } |
| 9583 | 9679 |
| 9584 | 9680 |
| 9585 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { | 9681 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { |
| 9586 if (function->has_initial_map()) return; | 9682 if (function->has_initial_map()) return; |
| 9587 Isolate* isolate = function->GetIsolate(); | 9683 Isolate* isolate = function->GetIsolate(); |
| 9588 | 9684 |
| 9589 // First create a new map with the size and number of in-object properties | 9685 // First create a new map with the size and number of in-object properties |
| 9590 // suggested by the function. | 9686 // suggested by the function. |
| 9591 InstanceType instance_type; | 9687 InstanceType instance_type; |
| (...skipping 2101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11693 } | 11789 } |
| 11694 UNREACHABLE(); | 11790 UNREACHABLE(); |
| 11695 return "?"; | 11791 return "?"; |
| 11696 } | 11792 } |
| 11697 | 11793 |
| 11698 | 11794 |
| 11699 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, | 11795 Handle<Map> Map::TransitionToPrototype(Handle<Map> map, |
| 11700 Handle<Object> prototype) { | 11796 Handle<Object> prototype) { |
| 11701 Handle<Map> new_map = GetPrototypeTransition(map, prototype); | 11797 Handle<Map> new_map = GetPrototypeTransition(map, prototype); |
| 11702 if (new_map.is_null()) { | 11798 if (new_map.is_null()) { |
| 11703 new_map = Copy(map); | 11799 new_map = Copy(map, "TransitionToPrototype"); |
| 11704 PutPrototypeTransition(map, prototype, new_map); | 11800 PutPrototypeTransition(map, prototype, new_map); |
| 11705 new_map->set_prototype(*prototype); | 11801 new_map->set_prototype(*prototype); |
| 11706 } | 11802 } |
| 11707 return new_map; | 11803 return new_map; |
| 11708 } | 11804 } |
| 11709 | 11805 |
| 11710 | 11806 |
| 11711 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, | 11807 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
| 11712 Handle<Object> value, | 11808 Handle<Object> value, |
| 11713 bool from_javascript) { | 11809 bool from_javascript) { |
| (...skipping 4853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16567 Handle<DependentCode> codes = | 16663 Handle<DependentCode> codes = |
| 16568 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), | 16664 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), |
| 16569 DependentCode::kPropertyCellChangedGroup, | 16665 DependentCode::kPropertyCellChangedGroup, |
| 16570 info->object_wrapper()); | 16666 info->object_wrapper()); |
| 16571 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 16667 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
| 16572 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16668 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| 16573 cell, info->zone()); | 16669 cell, info->zone()); |
| 16574 } | 16670 } |
| 16575 | 16671 |
| 16576 } } // namespace v8::internal | 16672 } } // namespace v8::internal |
| OLD | NEW |