| 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 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 // maps. | 895 // maps. |
| 896 isolate_->keyed_lookup_cache()->Clear(); | 896 isolate_->keyed_lookup_cache()->Clear(); |
| 897 isolate_->context_slot_cache()->Clear(); | 897 isolate_->context_slot_cache()->Clear(); |
| 898 isolate_->descriptor_lookup_cache()->Clear(); | 898 isolate_->descriptor_lookup_cache()->Clear(); |
| 899 StringSplitCache::Clear(string_split_cache()); | 899 StringSplitCache::Clear(string_split_cache()); |
| 900 | 900 |
| 901 isolate_->compilation_cache()->MarkCompactPrologue(); | 901 isolate_->compilation_cache()->MarkCompactPrologue(); |
| 902 | 902 |
| 903 CompletelyClearInstanceofCache(); | 903 CompletelyClearInstanceofCache(); |
| 904 | 904 |
| 905 FlushNumberStringCache(); | 905 // TODO(1605) select heuristic for flushing NumberString cache with |
| 906 // FlushNumberStringCache |
| 906 if (FLAG_cleanup_code_caches_at_gc) { | 907 if (FLAG_cleanup_code_caches_at_gc) { |
| 907 polymorphic_code_cache()->set_cache(undefined_value()); | 908 polymorphic_code_cache()->set_cache(undefined_value()); |
| 908 } | 909 } |
| 909 | 910 |
| 910 ClearNormalizedMapCaches(); | 911 ClearNormalizedMapCaches(); |
| 911 } | 912 } |
| 912 | 913 |
| 913 | 914 |
| 914 Object* Heap::FindCodeObject(Address a) { | 915 Object* Heap::FindCodeObject(Address a) { |
| 915 return isolate()->inner_pointer_to_code_cache()-> | 916 return isolate()->inner_pointer_to_code_cache()-> |
| (...skipping 1588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2504 // Allocate the dictionary of intrinsic function names. | 2505 // Allocate the dictionary of intrinsic function names. |
| 2505 { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions); | 2506 { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions); |
| 2506 if (!maybe_obj->ToObject(&obj)) return false; | 2507 if (!maybe_obj->ToObject(&obj)) return false; |
| 2507 } | 2508 } |
| 2508 { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this, | 2509 { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this, |
| 2509 obj); | 2510 obj); |
| 2510 if (!maybe_obj->ToObject(&obj)) return false; | 2511 if (!maybe_obj->ToObject(&obj)) return false; |
| 2511 } | 2512 } |
| 2512 set_intrinsic_function_names(StringDictionary::cast(obj)); | 2513 set_intrinsic_function_names(StringDictionary::cast(obj)); |
| 2513 | 2514 |
| 2514 { MaybeObject* maybe_obj = AllocateInitialNumberStringCache(); | 2515 if (InitializeNumberStringCache()->IsFailure()) return false; |
| 2515 if (!maybe_obj->ToObject(&obj)) return false; | |
| 2516 } | |
| 2517 set_number_string_cache(FixedArray::cast(obj)); | |
| 2518 | 2516 |
| 2519 // Allocate cache for single character ASCII strings. | 2517 // Allocate cache for single character ASCII strings. |
| 2520 { MaybeObject* maybe_obj = | 2518 { MaybeObject* maybe_obj = |
| 2521 AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED); | 2519 AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED); |
| 2522 if (!maybe_obj->ToObject(&obj)) return false; | 2520 if (!maybe_obj->ToObject(&obj)) return false; |
| 2523 } | 2521 } |
| 2524 set_single_character_string_cache(FixedArray::cast(obj)); | 2522 set_single_character_string_cache(FixedArray::cast(obj)); |
| 2525 | 2523 |
| 2526 // Allocate cache for string split. | 2524 // Allocate cache for string split. |
| 2527 { MaybeObject* maybe_obj = | 2525 { MaybeObject* maybe_obj = |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2617 } | 2615 } |
| 2618 | 2616 |
| 2619 | 2617 |
| 2620 void StringSplitCache::Clear(FixedArray* cache) { | 2618 void StringSplitCache::Clear(FixedArray* cache) { |
| 2621 for (int i = 0; i < kStringSplitCacheSize; i++) { | 2619 for (int i = 0; i < kStringSplitCacheSize; i++) { |
| 2622 cache->set(i, Smi::FromInt(0)); | 2620 cache->set(i, Smi::FromInt(0)); |
| 2623 } | 2621 } |
| 2624 } | 2622 } |
| 2625 | 2623 |
| 2626 | 2624 |
| 2627 MaybeObject* Heap::AllocateInitialNumberStringCache() { | 2625 MaybeObject* Heap::InitializeNumberStringCache() { |
| 2626 // Compute the size of the number string cache based on the max heap size. |
| 2627 // max_semispace_size_ == 512 KB => number_string_cache_size = 32. |
| 2628 // max_semispace_size_ == 8 MB => number_string_cache_size = 16KB. |
| 2629 int number_string_cache_size = max_semispace_size_ / 512; |
| 2630 number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size)); |
| 2631 Object* obj; |
| 2628 MaybeObject* maybe_obj = | 2632 MaybeObject* maybe_obj = |
| 2629 AllocateFixedArray(kInitialNumberStringCacheSize * 2, TENURED); | 2633 AllocateFixedArray(number_string_cache_size * 2, TENURED); |
| 2634 if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj)); |
| 2630 return maybe_obj; | 2635 return maybe_obj; |
| 2631 } | 2636 } |
| 2632 | 2637 |
| 2633 | 2638 |
| 2634 int Heap::FullSizeNumberStringCacheLength() { | |
| 2635 // Compute the size of the number string cache based on the max newspace size. | |
| 2636 // The number string cache has a minimum size based on twice the initial cache | |
| 2637 // size to ensure that it is bigger after being made 'full size'. | |
| 2638 int number_string_cache_size = max_semispace_size_ / 512; | |
| 2639 number_string_cache_size = Max(kInitialNumberStringCacheSize * 2, | |
| 2640 Min(0x4000, number_string_cache_size)); | |
| 2641 // There is a string and a number per entry so the length is twice the number | |
| 2642 // of entries. | |
| 2643 return number_string_cache_size * 2; | |
| 2644 } | |
| 2645 | |
| 2646 | |
| 2647 void Heap::AllocateFullSizeNumberStringCache() { | |
| 2648 // The idea is to have a small number string cache in the snapshot to keep | |
| 2649 // boot-time memory usage down. If we expand the number string cache already | |
| 2650 // while creating the snapshot then that didn't work out. | |
| 2651 ASSERT(!Serializer::enabled()); | |
| 2652 MaybeObject* maybe_obj = | |
| 2653 AllocateFixedArray(FullSizeNumberStringCacheLength(), TENURED); | |
| 2654 Object* new_cache; | |
| 2655 if (maybe_obj->ToObject(&new_cache)) { | |
| 2656 // We don't bother to repopulate the cache with entries from the old cache. | |
| 2657 // It will be repopulated soon enough with new strings. | |
| 2658 set_number_string_cache(FixedArray::cast(new_cache)); | |
| 2659 } | |
| 2660 // If allocation fails then we just return without doing anything. It is only | |
| 2661 // a cache, so best effort is OK here. | |
| 2662 } | |
| 2663 | |
| 2664 | |
| 2665 void Heap::FlushNumberStringCache() { | 2639 void Heap::FlushNumberStringCache() { |
| 2666 // Flush the number to string cache. | 2640 // Flush the number to string cache. |
| 2667 int len = number_string_cache()->length(); | 2641 int len = number_string_cache()->length(); |
| 2668 for (int i = 0; i < len; i++) { | 2642 for (int i = 0; i < len; i++) { |
| 2669 number_string_cache()->set_undefined(this, i); | 2643 number_string_cache()->set_undefined(this, i); |
| 2670 } | 2644 } |
| 2671 } | 2645 } |
| 2672 | 2646 |
| 2673 | 2647 |
| 2674 static inline int double_get_hash(double d) { | 2648 static inline int double_get_hash(double d) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2700 } | 2674 } |
| 2701 return undefined_value(); | 2675 return undefined_value(); |
| 2702 } | 2676 } |
| 2703 | 2677 |
| 2704 | 2678 |
| 2705 void Heap::SetNumberStringCache(Object* number, String* string) { | 2679 void Heap::SetNumberStringCache(Object* number, String* string) { |
| 2706 int hash; | 2680 int hash; |
| 2707 int mask = (number_string_cache()->length() >> 1) - 1; | 2681 int mask = (number_string_cache()->length() >> 1) - 1; |
| 2708 if (number->IsSmi()) { | 2682 if (number->IsSmi()) { |
| 2709 hash = smi_get_hash(Smi::cast(number)) & mask; | 2683 hash = smi_get_hash(Smi::cast(number)) & mask; |
| 2684 number_string_cache()->set(hash * 2, Smi::cast(number)); |
| 2710 } else { | 2685 } else { |
| 2711 hash = double_get_hash(number->Number()) & mask; | 2686 hash = double_get_hash(number->Number()) & mask; |
| 2687 number_string_cache()->set(hash * 2, number); |
| 2712 } | 2688 } |
| 2713 if (number_string_cache()->get(hash * 2) != undefined_value() && | |
| 2714 number_string_cache()->length() != FullSizeNumberStringCacheLength()) { | |
| 2715 // The first time we have a hash collision, we move to the full sized | |
| 2716 // number string cache. | |
| 2717 AllocateFullSizeNumberStringCache(); | |
| 2718 return; | |
| 2719 } | |
| 2720 number_string_cache()->set(hash * 2, number); | |
| 2721 number_string_cache()->set(hash * 2 + 1, string); | 2689 number_string_cache()->set(hash * 2 + 1, string); |
| 2722 } | 2690 } |
| 2723 | 2691 |
| 2724 | 2692 |
| 2725 MaybeObject* Heap::NumberToString(Object* number, | 2693 MaybeObject* Heap::NumberToString(Object* number, |
| 2726 bool check_number_string_cache) { | 2694 bool check_number_string_cache) { |
| 2727 isolate_->counters()->number_to_string_runtime()->Increment(); | 2695 isolate_->counters()->number_to_string_runtime()->Increment(); |
| 2728 if (check_number_string_cache) { | 2696 if (check_number_string_cache) { |
| 2729 Object* cached = GetNumberStringCache(number); | 2697 Object* cached = GetNumberStringCache(number); |
| 2730 if (cached != undefined_value()) { | 2698 if (cached != undefined_value()) { |
| (...skipping 4004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6735 isolate_->heap()->store_buffer()->Compact(); | 6703 isolate_->heap()->store_buffer()->Compact(); |
| 6736 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); | 6704 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); |
| 6737 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | 6705 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { |
| 6738 next = chunk->next_chunk(); | 6706 next = chunk->next_chunk(); |
| 6739 isolate_->memory_allocator()->Free(chunk); | 6707 isolate_->memory_allocator()->Free(chunk); |
| 6740 } | 6708 } |
| 6741 chunks_queued_for_free_ = NULL; | 6709 chunks_queued_for_free_ = NULL; |
| 6742 } | 6710 } |
| 6743 | 6711 |
| 6744 } } // namespace v8::internal | 6712 } } // namespace v8::internal |
| OLD | NEW |