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

Side by Side Diff: src/objects.cc

Issue 2021373002: Refactor Maps' code_cache (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: windows don't want no constexpr Created 4 years, 6 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
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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 "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 9429 matching lines...) Expand 10 before | Expand all | Expand 10 after
9440 9440
9441 SimpleTransitionFlag simple_flag = 9441 SimpleTransitionFlag simple_flag =
9442 (insertion_index == descriptors->number_of_descriptors() - 1) 9442 (insertion_index == descriptors->number_of_descriptors() - 1)
9443 ? SIMPLE_PROPERTY_TRANSITION 9443 ? SIMPLE_PROPERTY_TRANSITION
9444 : PROPERTY_TRANSITION; 9444 : PROPERTY_TRANSITION;
9445 return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor, 9445 return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
9446 flag, key, "CopyReplaceDescriptor", 9446 flag, key, "CopyReplaceDescriptor",
9447 simple_flag); 9447 simple_flag);
9448 } 9448 }
9449 9449
9450 // Helper class to manage a Map's code cache. The layout depends on the number
9451 // of entries; this is worthwhile because most code caches are very small,
9452 // but some are huge (thousands of entries).
9453 // For zero entries, the EmptyFixedArray is used.
9454 // For one entry, we use a 2-element FixedArray containing [name, code].
9455 // For 2..100 entries, we use a FixedArray with linear lookups, the layout is:
9456 // [0] - number of slots that are currently in use
9457 // [1] - first name
9458 // [2] - first code
9459 // [3] - second name
9460 // [4] - second code
9461 // etc.
9462 // For more than 128 entries, we use a CodeCacheHashTable.
9463 class CodeCache : public AllStatic {
9464 public:
9465 // Returns the new cache, to be stored on the map.
9466 static Handle<FixedArray> Put(Isolate* isolate, Handle<FixedArray> cache,
9467 Handle<Name> name, Handle<Code> code) {
9468 int length = cache->length();
9469 if (length == 0) return PutFirstElement(isolate, name, code);
9470 if (length == kEntrySize) {
9471 return PutSecondElement(isolate, cache, name, code);
9472 }
9473 if (length <= kLinearMaxSize) {
9474 Handle<FixedArray> result = PutLinearElement(isolate, cache, name, code);
9475 if (!result.is_null()) return result;
9476 // Fall through if linear storage is getting too large.
9477 }
9478 return PutHashTableElement(isolate, cache, name, code);
9479 }
9480
9481 static Code* Lookup(FixedArray* cache, Name* name, Code::Flags flags) {
9482 int length = cache->length();
9483 if (length == 0) return nullptr;
9484 if (length == kEntrySize) return OneElementLookup(cache, name, flags);
9485 if (!cache->IsCodeCacheHashTable()) {
9486 return LinearLookup(cache, name, flags);
9487 } else {
9488 return CodeCacheHashTable::cast(cache)->Lookup(name, flags);
9489 }
9490 }
9491
9492 private:
9493 static const int kNameIndex = 0;
9494 static const int kCodeIndex = 1;
9495 static const int kEntrySize = 2;
9496
9497 static const int kLinearUsageIndex = 0;
9498 static const int kLinearReservedSlots = 1;
9499 static const int kLinearInitialCapacity = 2;
9500 static const int kLinearMaxSize = 257; // == LinearSizeFor(128);
9501
9502 static const int kHashTableInitialCapacity = 200; // Number of entries.
9503
9504 static int LinearSizeFor(int entries) {
9505 return kLinearReservedSlots + kEntrySize * entries;
9506 }
9507
9508 static int LinearNewSize(int old_size) {
9509 int old_entries = (old_size - kLinearReservedSlots) / kEntrySize;
9510 return LinearSizeFor(old_entries * 2);
9511 }
9512
9513 static Code* OneElementLookup(FixedArray* cache, Name* name,
9514 Code::Flags flags) {
9515 DCHECK_EQ(cache->length(), kEntrySize);
9516 if (cache->get(kNameIndex) != name) return nullptr;
9517 Code* maybe_code = Code::cast(cache->get(kCodeIndex));
9518 if (maybe_code->flags() != flags) return nullptr;
9519 return maybe_code;
9520 }
9521
9522 static Code* LinearLookup(FixedArray* cache, Name* name, Code::Flags flags) {
9523 DCHECK_GE(cache->length(), kEntrySize);
9524 DCHECK(!cache->IsCodeCacheHashTable());
9525 int usage = GetLinearUsage(cache);
9526 for (int i = kLinearReservedSlots; i < usage; i += kEntrySize) {
9527 if (cache->get(i + kNameIndex) != name) continue;
9528 Code* code = Code::cast(cache->get(i + kCodeIndex));
9529 if (code->flags() == flags) return code;
9530 }
9531 return nullptr;
9532 }
9533
9534 static Handle<FixedArray> PutFirstElement(Isolate* isolate, Handle<Name> name,
9535 Handle<Code> code) {
9536 Handle<FixedArray> cache = isolate->factory()->NewFixedArray(kEntrySize);
9537 cache->set(kNameIndex, *name);
9538 cache->set(kCodeIndex, *code);
9539 return cache;
9540 }
9541
9542 static Handle<FixedArray> PutSecondElement(Isolate* isolate,
9543 Handle<FixedArray> cache,
9544 Handle<Name> name,
9545 Handle<Code> code) {
9546 DCHECK_EQ(cache->length(), kEntrySize);
9547 Handle<FixedArray> new_cache = isolate->factory()->NewFixedArray(
9548 LinearSizeFor(kLinearInitialCapacity));
9549 new_cache->set(kLinearReservedSlots + kNameIndex, cache->get(kNameIndex));
9550 new_cache->set(kLinearReservedSlots + kCodeIndex, cache->get(kCodeIndex));
9551 new_cache->set(LinearSizeFor(1) + kNameIndex, *name);
9552 new_cache->set(LinearSizeFor(1) + kCodeIndex, *code);
9553 new_cache->set(kLinearUsageIndex, Smi::FromInt(LinearSizeFor(2)));
9554 return new_cache;
9555 }
9556
9557 static Handle<FixedArray> PutLinearElement(Isolate* isolate,
9558 Handle<FixedArray> cache,
9559 Handle<Name> name,
9560 Handle<Code> code) {
9561 int length = cache->length();
9562 int usage = GetLinearUsage(*cache);
9563 DCHECK_LE(usage, length);
9564 // Check if we need to grow.
9565 if (usage == length) {
9566 int new_length = LinearNewSize(length);
9567 if (new_length > kLinearMaxSize) return Handle<FixedArray>::null();
9568 Handle<FixedArray> new_cache =
9569 isolate->factory()->NewFixedArray(new_length);
9570 for (int i = kLinearReservedSlots; i < length; i++) {
9571 new_cache->set(i, cache->get(i));
9572 }
9573 cache = new_cache;
9574 }
9575 // Store new entry.
9576 DCHECK_GE(cache->length(), usage + kEntrySize);
9577 cache->set(usage + kNameIndex, *name);
9578 cache->set(usage + kCodeIndex, *code);
9579 cache->set(kLinearUsageIndex, Smi::FromInt(usage + kEntrySize));
9580 return cache;
9581 }
9582
9583 static Handle<FixedArray> PutHashTableElement(Isolate* isolate,
9584 Handle<FixedArray> cache,
9585 Handle<Name> name,
9586 Handle<Code> code) {
9587 // Check if we need to transition from linear to hash table storage.
9588 if (!cache->IsCodeCacheHashTable()) {
9589 // Check that the initial hash table capacity is large enough.
9590 DCHECK_EQ(kLinearMaxSize, LinearSizeFor(128));
9591 STATIC_ASSERT(kHashTableInitialCapacity > 128);
9592
9593 int length = cache->length();
9594 // Only migrate from linear storage when it's full.
9595 DCHECK_EQ(length, GetLinearUsage(*cache));
9596 DCHECK_EQ(length, kLinearMaxSize);
9597 Handle<CodeCacheHashTable> table =
9598 CodeCacheHashTable::New(isolate, kHashTableInitialCapacity);
9599 HandleScope scope(isolate);
9600 for (int i = kLinearReservedSlots; i < length; i += kEntrySize) {
9601 Handle<Name> old_name(Name::cast(cache->get(i + kNameIndex)), isolate);
9602 Handle<Code> old_code(Code::cast(cache->get(i + kCodeIndex)), isolate);
9603 CodeCacheHashTable::Put(table, old_name, old_code);
9604 }
9605 cache = table;
9606 }
9607 // Store new entry.
9608 DCHECK(cache->IsCodeCacheHashTable());
9609 return CodeCacheHashTable::Put(Handle<CodeCacheHashTable>::cast(cache),
9610 name, code);
9611 }
9612
9613 static inline int GetLinearUsage(FixedArray* linear_cache) {
9614 DCHECK_GT(linear_cache->length(), kEntrySize);
9615 return Smi::cast(linear_cache->get(kLinearUsageIndex))->value();
9616 }
9617 };
9450 9618
9451 void Map::UpdateCodeCache(Handle<Map> map, 9619 void Map::UpdateCodeCache(Handle<Map> map,
9452 Handle<Name> name, 9620 Handle<Name> name,
9453 Handle<Code> code) { 9621 Handle<Code> code) {
9454 Isolate* isolate = map->GetIsolate(); 9622 Isolate* isolate = map->GetIsolate();
9455 HandleScope scope(isolate); 9623 Handle<FixedArray> cache(map->code_cache(), isolate);
9456 // Allocate the code cache if not present. 9624 Handle<FixedArray> new_cache = CodeCache::Put(isolate, cache, name, code);
9457 if (!map->has_code_cache()) {
9458 Handle<Object> result =
9459 CodeCacheHashTable::New(isolate, CodeCacheHashTable::kInitialSize);
9460 map->set_code_cache(*result);
9461 }
9462
9463 // Update the code cache.
9464 Handle<CodeCacheHashTable> cache(CodeCacheHashTable::cast(map->code_cache()),
9465 isolate);
9466 Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
9467 map->set_code_cache(*new_cache); 9625 map->set_code_cache(*new_cache);
9468 } 9626 }
9469 9627
9470 Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) { 9628 Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
9471 if (!has_code_cache()) return nullptr; 9629 return CodeCache::Lookup(code_cache(), name, flags);
9472 return CodeCacheHashTable::cast(code_cache())->Lookup(name, flags);
9473 } 9630 }
9474 9631
9475 9632
9476 // The key in the code cache hash table consists of the property name and the 9633 // The key in the code cache hash table consists of the property name and the
9477 // code object. The actual match is on the name and the code flags. If a key 9634 // code object. The actual match is on the name and the code flags. If a key
9478 // is created using the flags and not a code object it can only be used for 9635 // is created using the flags and not a code object it can only be used for
9479 // lookup not to create a new entry. 9636 // lookup not to create a new entry.
9480 class CodeCacheHashTableKey : public HashTableKey { 9637 class CodeCacheHashTableKey : public HashTableKey {
9481 public: 9638 public:
9482 CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags) 9639 CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
(...skipping 9103 matching lines...) Expand 10 before | Expand all | Expand 10 after
18586 if (cell->value() != *new_value) { 18743 if (cell->value() != *new_value) {
18587 cell->set_value(*new_value); 18744 cell->set_value(*new_value);
18588 Isolate* isolate = cell->GetIsolate(); 18745 Isolate* isolate = cell->GetIsolate();
18589 cell->dependent_code()->DeoptimizeDependentCodeGroup( 18746 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18590 isolate, DependentCode::kPropertyCellChangedGroup); 18747 isolate, DependentCode::kPropertyCellChangedGroup);
18591 } 18748 }
18592 } 18749 }
18593 18750
18594 } // namespace internal 18751 } // namespace internal
18595 } // namespace v8 18752 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698