diff options
author | Fedor Indutny <fedor@indutny.com> | 2014-10-10 14:49:02 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-10-10 14:49:02 +0400 |
commit | 6bcea4ff932144a5fd02affefd45164fbf471e67 (patch) | |
tree | a8e078c679b12f0daebe10ed254239cb0d79e146 /deps/v8/src/ic/stub-cache.cc | |
parent | 4fae2356d105e394115188a814097c4a95ae0c5d (diff) | |
download | android-node-v8-6bcea4ff932144a5fd02affefd45164fbf471e67.tar.gz android-node-v8-6bcea4ff932144a5fd02affefd45164fbf471e67.tar.bz2 android-node-v8-6bcea4ff932144a5fd02affefd45164fbf471e67.zip |
deps: update v8 to 3.29.93.1
Diffstat (limited to 'deps/v8/src/ic/stub-cache.cc')
-rw-r--r-- | deps/v8/src/ic/stub-cache.cc | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/deps/v8/src/ic/stub-cache.cc b/deps/v8/src/ic/stub-cache.cc new file mode 100644 index 0000000000..35a4acf8cc --- /dev/null +++ b/deps/v8/src/ic/stub-cache.cc @@ -0,0 +1,147 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/v8.h" + +#include "src/base/bits.h" +#include "src/ic/stub-cache.h" +#include "src/type-info.h" + +namespace v8 { +namespace internal { + + +StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {} + + +void StubCache::Initialize() { + DCHECK(base::bits::IsPowerOfTwo32(kPrimaryTableSize)); + DCHECK(base::bits::IsPowerOfTwo32(kSecondaryTableSize)); + Clear(); +} + + +static Code::Flags CommonStubCacheChecks(Name* name, Map* map, + Code::Flags flags) { + flags = Code::RemoveTypeAndHolderFromFlags(flags); + + // Validate that the name does not move on scavenge, and that we + // can use identity checks instead of structural equality checks. + DCHECK(!name->GetHeap()->InNewSpace(name)); + DCHECK(name->IsUniqueName()); + + // The state bits are not important to the hash function because the stub + // cache only contains handlers. Make sure that the bits are the least + // significant so they will be the ones masked out. + DCHECK_EQ(Code::HANDLER, Code::ExtractKindFromFlags(flags)); + STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1); + + // Make sure that the code type and cache holder are not included in the hash. + DCHECK(Code::ExtractTypeFromFlags(flags) == 0); + DCHECK(Code::ExtractCacheHolderFromFlags(flags) == 0); + + return flags; +} + + +Code* StubCache::Set(Name* name, Map* map, Code* code) { + Code::Flags flags = CommonStubCacheChecks(name, map, code->flags()); + + // Compute the primary entry. + int primary_offset = PrimaryOffset(name, flags, map); + Entry* primary = entry(primary_, primary_offset); + Code* old_code = primary->value; + + // If the primary entry has useful data in it, we retire it to the + // secondary cache before overwriting it. + if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { + Map* old_map = primary->map; + Code::Flags old_flags = + Code::RemoveTypeAndHolderFromFlags(old_code->flags()); + int seed = PrimaryOffset(primary->key, old_flags, old_map); + int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); + Entry* secondary = entry(secondary_, secondary_offset); + *secondary = *primary; + } + + // Update primary cache. + primary->key = name; + primary->value = code; + primary->map = map; + isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); + return code; +} + + +Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { + flags = CommonStubCacheChecks(name, map, flags); + int primary_offset = PrimaryOffset(name, flags, map); + Entry* primary = entry(primary_, primary_offset); + if (primary->key == name && primary->map == map) { + return primary->value; + } + int secondary_offset = SecondaryOffset(name, flags, primary_offset); + Entry* secondary = entry(secondary_, secondary_offset); + if (secondary->key == name && secondary->map == map) { + return secondary->value; + } + return NULL; +} + + +void StubCache::Clear() { + Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); + for (int i = 0; i < kPrimaryTableSize; i++) { + primary_[i].key = isolate()->heap()->empty_string(); + primary_[i].map = NULL; + primary_[i].value = empty; + } + for (int j = 0; j < kSecondaryTableSize; j++) { + secondary_[j].key = isolate()->heap()->empty_string(); + secondary_[j].map = NULL; + secondary_[j].value = empty; + } +} + + +void StubCache::CollectMatchingMaps(SmallMapList* types, Handle<Name> name, + Code::Flags flags, + Handle<Context> native_context, + Zone* zone) { + for (int i = 0; i < kPrimaryTableSize; i++) { + if (primary_[i].key == *name) { + Map* map = primary_[i].map; + // Map can be NULL, if the stub is constant function call + // with a primitive receiver. + if (map == NULL) continue; + + int offset = PrimaryOffset(*name, flags, map); + if (entry(primary_, offset) == &primary_[i] && + !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { + types->AddMapIfMissing(Handle<Map>(map), zone); + } + } + } + + for (int i = 0; i < kSecondaryTableSize; i++) { + if (secondary_[i].key == *name) { + Map* map = secondary_[i].map; + // Map can be NULL, if the stub is constant function call + // with a primitive receiver. + if (map == NULL) continue; + + // Lookup in primary table and skip duplicates. + int primary_offset = PrimaryOffset(*name, flags, map); + + // Lookup in secondary table and add matches. + int offset = SecondaryOffset(*name, flags, primary_offset); + if (entry(secondary_, offset) == &secondary_[i] && + !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { + types->AddMapIfMissing(Handle<Map>(map), zone); + } + } + } +} +} +} // namespace v8::internal |