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

Side by Side Diff: src/heap.cc

Issue 8341014: Age the number string cache so it does not keep strings Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 // maps. 823 // maps.
824 isolate_->keyed_lookup_cache()->Clear(); 824 isolate_->keyed_lookup_cache()->Clear();
825 isolate_->context_slot_cache()->Clear(); 825 isolate_->context_slot_cache()->Clear();
826 isolate_->descriptor_lookup_cache()->Clear(); 826 isolate_->descriptor_lookup_cache()->Clear();
827 StringSplitCache::Clear(string_split_cache()); 827 StringSplitCache::Clear(string_split_cache());
828 828
829 isolate_->compilation_cache()->MarkCompactPrologue(); 829 isolate_->compilation_cache()->MarkCompactPrologue();
830 830
831 CompletelyClearInstanceofCache(); 831 CompletelyClearInstanceofCache();
832 832
833 // TODO(1605) select heuristic for flushing NumberString cache with 833 // TODO(1605) select heuristic for flushing NumberString cache with
Vyacheslav Egorov (Chromium) 2011/10/18 15:30:39 remove todo?
834 // FlushNumberStringCache 834 AgeNumberStringCache();
835 if (FLAG_cleanup_code_caches_at_gc) { 835 if (FLAG_cleanup_code_caches_at_gc) {
836 polymorphic_code_cache()->set_cache(undefined_value()); 836 polymorphic_code_cache()->set_cache(undefined_value());
837 } 837 }
838 838
839 ClearNormalizedMapCaches(); 839 ClearNormalizedMapCaches();
840 } 840 }
841 841
842 842
843 Object* Heap::FindCodeObject(Address a) { 843 Object* Heap::FindCodeObject(Address a) {
844 return isolate()->inner_pointer_to_code_cache()-> 844 return isolate()->inner_pointer_to_code_cache()->
(...skipping 1608 matching lines...) Expand 10 before | Expand all | Expand 10 after
2453 2453
2454 void StringSplitCache::Clear(FixedArray* cache) { 2454 void StringSplitCache::Clear(FixedArray* cache) {
2455 for (int i = 0; i < kStringSplitCacheSize; i++) { 2455 for (int i = 0; i < kStringSplitCacheSize; i++) {
2456 cache->set(i, Smi::FromInt(0)); 2456 cache->set(i, Smi::FromInt(0));
2457 } 2457 }
2458 } 2458 }
2459 2459
2460 2460
2461 MaybeObject* Heap::InitializeNumberStringCache() { 2461 MaybeObject* Heap::InitializeNumberStringCache() {
2462 // Compute the size of the number string cache based on the max heap size. 2462 // Compute the size of the number string cache based on the max heap size.
2463 // max_semispace_size_ == 512 KB => number_string_cache_size = 32. 2463 // max_semispace_size_ == 512kbyte => number_string_cache_size = 1kbyte.
2464 // max_semispace_size_ == 8 MB => number_string_cache_size = 16KB. 2464 // max_semispace_size_ == 8Mbyte => number_string_cache_size = 16kbyte.
2465 int number_string_cache_size = max_semispace_size_ / 512; 2465 int number_string_cache_size = max_semispace_size_ / 512;
2466 number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size)); 2466 number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size));
2467 number_string_cache_size = RoundUpToPowerOf2(number_string_cache_size);
2467 Object* obj; 2468 Object* obj;
2468 MaybeObject* maybe_obj = 2469 MaybeObject* maybe_obj =
2469 AllocateFixedArray(number_string_cache_size * 2, TENURED); 2470 AllocateFixedArray(number_string_cache_size * kNSCSlotsPerEntry, TENURED);
2470 if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj)); 2471 if (maybe_obj->ToObject(&obj)) {
2472 set_number_string_cache(FixedArray::cast(obj));
2473 FixedArray* array = FixedArray::cast(obj);
2474 for (int i = 0;
2475 i < number_string_cache_size * kNSCSlotsPerEntry;
2476 i += kNSCSlotsPerEntry) {
2477 array->set_undefined(this, i + kNSCNumberOffset);
2478 array->set_undefined(this, i + kNSCStringOffset);
2479 array->set(i + kNSCAgeOffset, Smi::FromInt(-1));
2480 }
2481 }
2471 return maybe_obj; 2482 return maybe_obj;
2472 } 2483 }
2473 2484
2474 2485
2475 void Heap::FlushNumberStringCache() { 2486 void Heap::AgeNumberStringCache() {
2476 // Flush the number to string cache. 2487 // Flush the number to string cache. The cache is laidout as a number of
2488 // cache entries. Each entry has first the number, then the string, then an
2489 // age mark. The age mark is -1 for an unused entry or n for a entry that
2490 // hasn't been used for the last n GC intervals.
2477 int len = number_string_cache()->length(); 2491 int len = number_string_cache()->length();
2478 for (int i = 0; i < len; i++) { 2492 ASSERT(len % kNSCSlotsPerEntry == 0);
2479 number_string_cache()->set_undefined(this, i); 2493 STATIC_ASSERT(kNSCSlotsPerEntry == 3); // This is needed for the next assert.
2494 ASSERT(IsPowerOf2(len & (len >> 1))); // Two thirds of len is a power of 2.
2495 for (int i = 0; i < len; i += kNSCSlotsPerEntry) {
2496 int recently_used =
2497 Smi::cast(number_string_cache()->get(i + kNSCAgeOffset))->value();
2498 if (recently_used >= kNSCMinAge) {
2499 recently_used++;
2500 if (recently_used > kNSCMaxAge) {
2501 // Not used for too long. Remove from cache.
2502 number_string_cache()->set(i + kNSCAgeOffset, Smi::FromInt(-1));
2503 number_string_cache()->set_undefined(this + kNSCNumberOffset, i);
2504 number_string_cache()->set_undefined(this, i + kNSCStringOffset);
2505 } else {
2506 // Age the entry.
2507 number_string_cache()->set(i + kNSCAgeOffset,
2508 Smi::FromInt(recently_used));
2509 ASSERT(number_string_cache()->get(i + kNSCNumberOffset)->IsNumber());
2510 ASSERT(number_string_cache()->get(i + kNSCStringOffset)->IsString());
2511 }
2512 } else {
2513 // Unused slot.
2514 ASSERT(recently_used == kNSCUnusedAge);
2515 ASSERT(number_string_cache()->get(i + kNSCNumberOffset)->IsUndefined());
2516 ASSERT(number_string_cache()->get(i + kNSCStringOffset)->IsUndefined());
2517 }
2480 } 2518 }
2481 } 2519 }
2482 2520
2483 2521
2484 static inline int double_get_hash(double d) { 2522 static inline int double_get_hash(double d) {
2485 DoubleRepresentation rep(d); 2523 DoubleRepresentation rep(d);
2486 return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32); 2524 return static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32);
2487 } 2525 }
2488 2526
2489 2527
2490 static inline int smi_get_hash(Smi* smi) {
2491 return smi->value();
2492 }
2493
2494
2495 Object* Heap::GetNumberStringCache(Object* number) { 2528 Object* Heap::GetNumberStringCache(Object* number) {
2496 int hash; 2529 int hash;
2497 int mask = (number_string_cache()->length() >> 1) - 1; 2530 int len = number_string_cache()->length();
2531 ASSERT(len % kNSCSlotsPerEntry == 0);
2532 STATIC_ASSERT(kNSCSlotsPerEntry == 3);
2533 len &= len >> 1; // Divide len by 3.
2534 ASSERT(IsPowerOf2(len));
2535 int mask = len - 1;
2498 if (number->IsSmi()) { 2536 if (number->IsSmi()) {
2499 hash = smi_get_hash(Smi::cast(number)) & mask; 2537 hash = (Smi::cast(number)->value() & mask);
2500 } else { 2538 } else {
2501 hash = double_get_hash(number->Number()) & mask; 2539 hash = double_get_hash(number->Number()) & mask;
2502 } 2540 }
2503 Object* key = number_string_cache()->get(hash * 2); 2541 hash *= kNSCSlotsPerEntry;
2504 if (key == number) { 2542 Object* key = number_string_cache()->get(hash + kNSCNumberOffset);
2505 return String::cast(number_string_cache()->get(hash * 2 + 1)); 2543 if (key == number ||
2506 } else if (key->IsHeapNumber() && 2544 (key->IsHeapNumber() &&
2507 number->IsHeapNumber() && 2545 number->IsHeapNumber() &&
2508 key->Number() == number->Number()) { 2546 key->Number() == number->Number())) {
2509 return String::cast(number_string_cache()->get(hash * 2 + 1)); 2547 // Reset age field.
2548 number_string_cache()->set(hash + kNSCAgeOffset, Smi::FromInt(kNSCMinAge));
2549 // Cache hit.
2550 return String::cast(number_string_cache()->get(hash + kNSCStringOffset));
2510 } 2551 }
2511 return undefined_value(); 2552 return undefined_value();
2512 } 2553 }
2513 2554
2514 2555
2515 void Heap::SetNumberStringCache(Object* number, String* string) { 2556 void Heap::SetNumberStringCache(Object* number, String* string) {
2516 int hash; 2557 int hash;
2517 int mask = (number_string_cache()->length() >> 1) - 1; 2558 int len = number_string_cache()->length();
2559 ASSERT(len % kNSCSlotsPerEntry == 0);
2560 STATIC_ASSERT(kNSCSlotsPerEntry == 3);
2561 len &= len >> 1; // Divide len by 3.
2562 ASSERT(IsPowerOf2(len));
2563 int mask = len - 1;
2518 if (number->IsSmi()) { 2564 if (number->IsSmi()) {
2519 hash = smi_get_hash(Smi::cast(number)) & mask; 2565 hash = (Smi::cast(number)->value() & mask) * kNSCSlotsPerEntry;
2520 number_string_cache()->set(hash * 2, Smi::cast(number)); 2566 number_string_cache()->set(hash + kNSCNumberOffset, Smi::cast(number));
2521 } else { 2567 } else {
2522 hash = double_get_hash(number->Number()) & mask; 2568 hash = (double_get_hash(number->Number()) & mask) * kNSCSlotsPerEntry;
2523 number_string_cache()->set(hash * 2, number); 2569 number_string_cache()->set(hash + kNSCNumberOffset, number);
2524 } 2570 }
2525 number_string_cache()->set(hash * 2 + 1, string); 2571 number_string_cache()->set(hash + kNSCStringOffset, string);
2572 // Reset age field.
2573 number_string_cache()->set(hash + kNSCAgeOffset, Smi::FromInt(kNSCMinAge));
2526 } 2574 }
2527 2575
2528 2576
2529 MaybeObject* Heap::NumberToString(Object* number, 2577 MaybeObject* Heap::NumberToString(Object* number,
2530 bool check_number_string_cache) { 2578 bool check_number_string_cache) {
2531 isolate_->counters()->number_to_string_runtime()->Increment(); 2579 isolate_->counters()->number_to_string_runtime()->Increment();
2532 if (check_number_string_cache) { 2580 if (check_number_string_cache) {
2533 Object* cached = GetNumberStringCache(number); 2581 Object* cached = GetNumberStringCache(number);
2534 if (cached != undefined_value()) { 2582 if (cached != undefined_value()) {
2535 return cached; 2583 return cached;
(...skipping 3870 matching lines...) Expand 10 before | Expand all | Expand 10 after
6406 isolate_->heap()->store_buffer()->Compact(); 6454 isolate_->heap()->store_buffer()->Compact();
6407 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); 6455 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
6408 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { 6456 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
6409 next = chunk->next_chunk(); 6457 next = chunk->next_chunk();
6410 isolate_->memory_allocator()->Free(chunk); 6458 isolate_->memory_allocator()->Free(chunk);
6411 } 6459 }
6412 chunks_queued_for_free_ = NULL; 6460 chunks_queued_for_free_ = NULL;
6413 } 6461 }
6414 6462
6415 } } // namespace v8::internal 6463 } } // namespace v8::internal
OLDNEW
« src/heap.h ('K') | « src/heap.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698