OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3328 | 3328 |
3329 // The global object is always normalized. | 3329 // The global object is always normalized. |
3330 ASSERT(!IsGlobalObject()); | 3330 ASSERT(!IsGlobalObject()); |
3331 // JSGlobalProxy must never be normalized | 3331 // JSGlobalProxy must never be normalized |
3332 ASSERT(!IsJSGlobalProxy()); | 3332 ASSERT(!IsJSGlobalProxy()); |
3333 | 3333 |
3334 Map* map_of_this = map(); | 3334 Map* map_of_this = map(); |
3335 | 3335 |
3336 // Allocate new content. | 3336 // Allocate new content. |
3337 int real_size = map_of_this->NumberOfOwnDescriptors(); | 3337 int real_size = map_of_this->NumberOfOwnDescriptors(); |
3338 int property_count = | 3338 int property_count = real_size; |
3339 map_of_this->NumberOfDescribedProperties(OWN_DESCRIPTORS); | |
3340 if (expected_additional_properties > 0) { | 3339 if (expected_additional_properties > 0) { |
3341 property_count += expected_additional_properties; | 3340 property_count += expected_additional_properties; |
3342 } else { | 3341 } else { |
3343 property_count += 2; // Make space for two more properties. | 3342 property_count += 2; // Make space for two more properties. |
3344 } | 3343 } |
3345 StringDictionary* dictionary; | 3344 StringDictionary* dictionary; |
3346 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); | 3345 MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count); |
3347 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 3346 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
3348 | 3347 |
3349 DescriptorArray* descs = map_of_this->instance_descriptors(); | 3348 DescriptorArray* descs = map_of_this->instance_descriptors(); |
(...skipping 4093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7443 | 7442 |
7444 // Clear a possible back pointer in case the transition leads to a dead map. | 7443 // Clear a possible back pointer in case the transition leads to a dead map. |
7445 // Return true in case a back pointer has been cleared and false otherwise. | 7444 // Return true in case a back pointer has been cleared and false otherwise. |
7446 static bool ClearBackPointer(Heap* heap, Map* target) { | 7445 static bool ClearBackPointer(Heap* heap, Map* target) { |
7447 if (Marking::MarkBitFrom(target).Get()) return false; | 7446 if (Marking::MarkBitFrom(target).Get()) return false; |
7448 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); | 7447 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); |
7449 return true; | 7448 return true; |
7450 } | 7449 } |
7451 | 7450 |
7452 | 7451 |
| 7452 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) { |
| 7453 int live_enum = map->EnumLength(); |
| 7454 if (live_enum == Map::kInvalidEnumCache) { |
| 7455 live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); |
| 7456 } |
| 7457 if (live_enum == 0) return descriptors->ClearEnumCache(); |
| 7458 |
| 7459 FixedArray* enum_cache = descriptors->GetEnumCache(); |
| 7460 |
| 7461 int to_trim = enum_cache->length() - live_enum; |
| 7462 if (to_trim <= 0) return; |
| 7463 RightTrimFixedArray<FROM_GC>(heap, descriptors->GetEnumCache(), to_trim); |
| 7464 |
| 7465 if (!descriptors->HasEnumIndicesCache()) return; |
| 7466 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); |
| 7467 RightTrimFixedArray<FROM_GC>(heap, enum_indices_cache, to_trim); |
| 7468 } |
| 7469 |
| 7470 |
| 7471 static void TrimDescriptorArray(Heap* heap, |
| 7472 Map* map, |
| 7473 DescriptorArray* descriptors, |
| 7474 int number_of_own_descriptors) { |
| 7475 int number_of_descriptors = descriptors->number_of_descriptors(); |
| 7476 int to_trim = number_of_descriptors - number_of_own_descriptors; |
| 7477 if (to_trim <= 0) return; |
| 7478 |
| 7479 // Maximally keep 50% of unused descriptors. |
| 7480 int keep = Min(to_trim, number_of_own_descriptors / 2); |
| 7481 for (int i = number_of_own_descriptors; |
| 7482 i < number_of_own_descriptors + keep; |
| 7483 ++i) { |
| 7484 descriptors->EraseDescriptor(heap, i); |
| 7485 } |
| 7486 |
| 7487 if (to_trim > keep) { |
| 7488 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep); |
| 7489 } |
| 7490 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); |
| 7491 |
| 7492 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); |
| 7493 descriptors->Sort(); |
| 7494 } |
| 7495 |
| 7496 |
7453 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, | 7497 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, |
7454 // because it cannot be called from outside the GC and we already have methods | 7498 // because it cannot be called from outside the GC and we already have methods |
7455 // depending on the transitions layout in the GC anyways. | 7499 // depending on the transitions layout in the GC anyways. |
7456 void Map::ClearNonLiveTransitions(Heap* heap) { | 7500 void Map::ClearNonLiveTransitions(Heap* heap) { |
7457 // If there are no transitions to be cleared, return. | 7501 // If there are no transitions to be cleared, return. |
7458 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7502 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7459 // properly cleared. | 7503 // properly cleared. |
7460 if (!HasTransitionArray()) return; | 7504 if (!HasTransitionArray()) return; |
7461 | 7505 |
7462 TransitionArray* t = transitions(); | 7506 TransitionArray* t = transitions(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7501 // If there are no transitions to be cleared, return. | 7545 // If there are no transitions to be cleared, return. |
7502 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7546 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7503 // properly cleared. | 7547 // properly cleared. |
7504 if (transition_index == t->number_of_transitions()) return; | 7548 if (transition_index == t->number_of_transitions()) return; |
7505 } | 7549 } |
7506 | 7550 |
7507 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 7551 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
7508 | 7552 |
7509 if (descriptors_owner_died) { | 7553 if (descriptors_owner_died) { |
7510 if (number_of_own_descriptors > 0) { | 7554 if (number_of_own_descriptors > 0) { |
7511 int number_of_descriptors = descriptors->number_of_descriptors(); | 7555 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); |
7512 int to_trim = number_of_descriptors - number_of_own_descriptors; | |
7513 if (to_trim > 0) { | |
7514 // Maximally keep 50% of unused descriptors. | |
7515 int keep = Min(to_trim, number_of_own_descriptors / 2); | |
7516 for (int i = number_of_own_descriptors; | |
7517 i < number_of_own_descriptors + keep; | |
7518 ++i) { | |
7519 descriptors->EraseDescriptor(heap, i); | |
7520 } | |
7521 if (to_trim > keep) { | |
7522 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep); | |
7523 } | |
7524 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); | |
7525 if (descriptors->HasEnumCache()) { | |
7526 int live_enum = | |
7527 NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); | |
7528 if (live_enum == 0) { | |
7529 descriptors->ClearEnumCache(); | |
7530 } else { | |
7531 FixedArray* enum_cache = descriptors->GetEnumCache(); | |
7532 to_trim = enum_cache->length() - live_enum; | |
7533 if (to_trim > 0) { | |
7534 RightTrimFixedArray<FROM_GC>( | |
7535 heap, descriptors->GetEnumCache(), to_trim); | |
7536 if (descriptors->HasEnumIndicesCache()) { | |
7537 RightTrimFixedArray<FROM_GC>( | |
7538 heap, descriptors->GetEnumIndicesCache(), to_trim); | |
7539 } | |
7540 } | |
7541 } | |
7542 } | |
7543 descriptors->Sort(); | |
7544 } | |
7545 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 7556 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
7546 } else { | 7557 } else { |
7547 t->set_descriptors(heap->empty_descriptor_array()); | 7558 t->set_descriptors(heap->empty_descriptor_array()); |
7548 } | 7559 } |
7549 set_owns_descriptors(true); | 7560 set_owns_descriptors(true); |
7550 } | 7561 } |
7551 | 7562 |
7552 // If the final transition array does not contain any live transitions, remove | 7563 // If the final transition array does not contain any live transitions, remove |
7553 // the transition array from the map. | 7564 // the transition array from the map. |
7554 if (transition_index == 0 && | 7565 if (transition_index == 0 && |
(...skipping 3117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10672 } | 10683 } |
10673 } | 10684 } |
10674 | 10685 |
10675 LookupResult result(isolate); | 10686 LookupResult result(isolate); |
10676 LocalLookupRealNamedProperty(key, &result); | 10687 LocalLookupRealNamedProperty(key, &result); |
10677 return result.IsPropertyCallbacks(); | 10688 return result.IsPropertyCallbacks(); |
10678 } | 10689 } |
10679 | 10690 |
10680 | 10691 |
10681 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 10692 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
10682 return HasFastProperties() ? | 10693 if (HasFastProperties()) { |
10683 map()->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter) : | 10694 Map* map = this->map(); |
10684 property_dictionary()->NumberOfElementsFilterAttributes(filter); | 10695 if (filter == NONE) return map->NumberOfOwnDescriptors(); |
| 10696 if (filter == DONT_ENUM) { |
| 10697 int result = map->EnumLength(); |
| 10698 if (result != Map::kInvalidEnumCache) return result; |
| 10699 } |
| 10700 return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter); |
| 10701 } |
| 10702 return property_dictionary()->NumberOfElementsFilterAttributes(filter); |
10685 } | 10703 } |
10686 | 10704 |
10687 | 10705 |
10688 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { | 10706 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { |
10689 Object* temp = get(i); | 10707 Object* temp = get(i); |
10690 set(i, get(j)); | 10708 set(i, get(j)); |
10691 set(j, temp); | 10709 set(j, temp); |
10692 if (this != numbers) { | 10710 if (this != numbers) { |
10693 temp = numbers->get(i); | 10711 temp = numbers->get(i); |
10694 numbers->set(i, Smi::cast(numbers->get(j))); | 10712 numbers->set(i, Smi::cast(numbers->get(j))); |
(...skipping 2833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13528 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13546 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13529 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13547 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13530 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13548 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13531 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13549 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13532 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13550 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13533 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13551 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13534 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13552 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13535 } | 13553 } |
13536 | 13554 |
13537 } } // namespace v8::internal | 13555 } } // namespace v8::internal |
OLD | NEW |