LCOV - code coverage report
Current view: top level - src/ic - stub-cache.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 36 52 69.2 %
Date: 2017-04-26 Functions: 5 6 83.3 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/ic/stub-cache.h"
       6             : 
       7             : #include "src/ast/ast.h"
       8             : #include "src/base/bits.h"
       9             : #include "src/counters.h"
      10             : #include "src/heap/heap.h"
      11             : #include "src/ic/ic-inl.h"
      12             : #include "src/type-info.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17      121571 : StubCache::StubCache(Isolate* isolate, Code::Kind ic_kind)
      18      121571 :     : isolate_(isolate), ic_kind_(ic_kind) {
      19             :   // Ensure the nullptr (aka Smi::kZero) which StubCache::Get() returns
      20             :   // when the entry is not found is not considered as a handler.
      21             :   DCHECK(!IC::IsHandler(nullptr));
      22      121571 : }
      23             : 
      24      121564 : void StubCache::Initialize() {
      25             :   DCHECK(base::bits::IsPowerOfTwo32(kPrimaryTableSize));
      26             :   DCHECK(base::bits::IsPowerOfTwo32(kSecondaryTableSize));
      27             :   Clear();
      28      121564 : }
      29             : 
      30             : #ifdef DEBUG
      31             : namespace {
      32             : 
      33             : bool CommonStubCacheChecks(StubCache* stub_cache, Name* name, Map* map,
      34             :                            Object* handler) {
      35             :   // Validate that the name and handler do not move on scavenge, and that we
      36             :   // can use identity checks instead of structural equality checks.
      37             :   DCHECK(!name->GetHeap()->InNewSpace(name));
      38             :   DCHECK(!name->GetHeap()->InNewSpace(handler));
      39             :   DCHECK(name->IsUniqueName());
      40             :   DCHECK(name->HasHashCode());
      41             :   if (handler) {
      42             :     DCHECK(IC::IsHandler(handler));
      43             :     if (handler->IsCode()) {
      44             :       Code* code = Code::cast(handler);
      45             :       Code::Flags expected_flags =
      46             :           Code::ComputeHandlerFlags(stub_cache->ic_kind());
      47             :       Code::Flags flags = code->flags();
      48             :       DCHECK_EQ(expected_flags, flags);
      49             :       DCHECK_EQ(Code::HANDLER, Code::ExtractKindFromFlags(code->flags()));
      50             :     }
      51             :   }
      52             :   return true;
      53             : }
      54             : 
      55             : }  // namespace
      56             : #endif
      57             : 
      58     2843270 : Object* StubCache::Set(Name* name, Map* map, Object* handler) {
      59             :   DCHECK(CommonStubCacheChecks(this, name, map, handler));
      60             : 
      61             :   // Compute the primary entry.
      62             :   int primary_offset = PrimaryOffset(name, map);
      63     1421635 :   Entry* primary = entry(primary_, primary_offset);
      64     1421635 :   Object* old_handler = primary->value;
      65             : 
      66             :   // If the primary entry has useful data in it, we retire it to the
      67             :   // secondary cache before overwriting it.
      68     2843270 :   if (old_handler != isolate_->builtins()->builtin(Builtins::kIllegal)) {
      69      503597 :     Map* old_map = primary->map;
      70      503597 :     int seed = PrimaryOffset(primary->key, old_map);
      71             :     int secondary_offset = SecondaryOffset(primary->key, seed);
      72      503597 :     Entry* secondary = entry(secondary_, secondary_offset);
      73      503597 :     *secondary = *primary;
      74             :   }
      75             : 
      76             :   // Update primary cache.
      77     1421635 :   primary->key = name;
      78     1421635 :   primary->value = handler;
      79     1421635 :   primary->map = map;
      80     1421635 :   isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
      81     1421635 :   return handler;
      82             : }
      83             : 
      84       35969 : Object* StubCache::Get(Name* name, Map* map) {
      85             :   DCHECK(CommonStubCacheChecks(this, name, map, nullptr));
      86             :   int primary_offset = PrimaryOffset(name, map);
      87       35969 :   Entry* primary = entry(primary_, primary_offset);
      88       35969 :   if (primary->key == name && primary->map == map) {
      89        1753 :     return primary->value;
      90             :   }
      91             :   int secondary_offset = SecondaryOffset(name, primary_offset);
      92       34216 :   Entry* secondary = entry(secondary_, secondary_offset);
      93       34216 :   if (secondary->key == name && secondary->map == map) {
      94         409 :     return secondary->value;
      95             :   }
      96             :   return nullptr;
      97             : }
      98             : 
      99             : 
     100      106699 : void StubCache::Clear() {
     101      228263 :   Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
     102   466970827 :   for (int i = 0; i < kPrimaryTableSize; i++) {
     103   466864128 :     primary_[i].key = isolate()->heap()->empty_string();
     104   466864128 :     primary_[i].map = nullptr;
     105   466864128 :     primary_[i].value = empty;
     106             :   }
     107   116802560 :   for (int j = 0; j < kSecondaryTableSize; j++) {
     108   116802560 :     secondary_[j].key = isolate()->heap()->empty_string();
     109   116802560 :     secondary_[j].map = nullptr;
     110   116802560 :     secondary_[j].value = empty;
     111             :   }
     112      106699 : }
     113             : 
     114             : 
     115           0 : void StubCache::CollectMatchingMaps(SmallMapList* types, Handle<Name> name,
     116             :                                     Handle<Context> native_context,
     117             :                                     Zone* zone) {
     118           0 :   for (int i = 0; i < kPrimaryTableSize; i++) {
     119           0 :     if (primary_[i].key == *name) {
     120           0 :       Map* map = primary_[i].map;
     121             :       // Map can be nullptr, if the stub is constant function call
     122             :       // with a primitive receiver.
     123           0 :       if (map == nullptr) continue;
     124             : 
     125             :       int offset = PrimaryOffset(*name, map);
     126           0 :       if (entry(primary_, offset) == &primary_[i] &&
     127           0 :           TypeFeedbackOracle::IsRelevantFeedback(map, *native_context)) {
     128           0 :         types->AddMapIfMissing(Handle<Map>(map), zone);
     129             :       }
     130             :     }
     131             :   }
     132             : 
     133           0 :   for (int i = 0; i < kSecondaryTableSize; i++) {
     134           0 :     if (secondary_[i].key == *name) {
     135           0 :       Map* map = secondary_[i].map;
     136             :       // Map can be nullptr, if the stub is constant function call
     137             :       // with a primitive receiver.
     138           0 :       if (map == nullptr) continue;
     139             : 
     140             :       // Lookup in primary table and skip duplicates.
     141             :       int primary_offset = PrimaryOffset(*name, map);
     142             : 
     143             :       // Lookup in secondary table and add matches.
     144             :       int offset = SecondaryOffset(*name, primary_offset);
     145           0 :       if (entry(secondary_, offset) == &secondary_[i] &&
     146           0 :           TypeFeedbackOracle::IsRelevantFeedback(map, *native_context)) {
     147           0 :         types->AddMapIfMissing(Handle<Map>(map), zone);
     148             :       }
     149             :     }
     150             :   }
     151           0 : }
     152             : }  // namespace internal
     153             : }  // namespace v8

Generated by: LCOV version 1.10