Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |