1a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
3a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org// found in the LICENSE file.
4a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
5a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/v8.h"
6a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org#include "src/base/bits.h"
8a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/ic/stub-cache.h"
9a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org#include "src/type-info.h"
10a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
11a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgnamespace v8 {
12a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgnamespace internal {
13a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
14a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
15a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgStubCache::StubCache(Isolate* isolate) : isolate_(isolate) {}
16a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
17a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
18a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgvoid StubCache::Initialize() {
1921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  DCHECK(base::bits::IsPowerOfTwo32(kPrimaryTableSize));
2021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  DCHECK(base::bits::IsPowerOfTwo32(kSecondaryTableSize));
21a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Clear();
22a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
23a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
24a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
25a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgstatic Code::Flags CommonStubCacheChecks(Name* name, Map* map,
26a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org                                         Code::Flags flags) {
27a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  flags = Code::RemoveTypeAndHolderFromFlags(flags);
28a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
29a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // Validate that the name does not move on scavenge, and that we
30a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // can use identity checks instead of structural equality checks.
31a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  DCHECK(!name->GetHeap()->InNewSpace(name));
32a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  DCHECK(name->IsUniqueName());
33a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
34a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // The state bits are not important to the hash function because the stub
35a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // cache only contains handlers. Make sure that the bits are the least
36a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // significant so they will be the ones masked out.
37a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  DCHECK_EQ(Code::HANDLER, Code::ExtractKindFromFlags(flags));
38a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
39a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
40a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // Make sure that the code type and cache holder are not included in the hash.
41a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
42a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  DCHECK(Code::ExtractCacheHolderFromFlags(flags) == 0);
43a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
44a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  return flags;
45a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
46a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
47a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
48a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgCode* StubCache::Set(Name* name, Map* map, Code* code) {
49a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Code::Flags flags = CommonStubCacheChecks(name, map, code->flags());
50a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
51a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // Compute the primary entry.
52a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  int primary_offset = PrimaryOffset(name, flags, map);
53a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Entry* primary = entry(primary_, primary_offset);
54a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Code* old_code = primary->value;
55a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
56a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // If the primary entry has useful data in it, we retire it to the
57a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // secondary cache before overwriting it.
58a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
59a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    Map* old_map = primary->map;
60a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    Code::Flags old_flags =
61a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org        Code::RemoveTypeAndHolderFromFlags(old_code->flags());
62a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    int seed = PrimaryOffset(primary->key, old_flags, old_map);
63a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
64a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    Entry* secondary = entry(secondary_, secondary_offset);
65a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    *secondary = *primary;
66a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
67a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
68a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  // Update primary cache.
69a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  primary->key = name;
70a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  primary->value = code;
71a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  primary->map = map;
72a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
73a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  return code;
74a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
75a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
76a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
77a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgCode* StubCache::Get(Name* name, Map* map, Code::Flags flags) {
78a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  flags = CommonStubCacheChecks(name, map, flags);
79a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  int primary_offset = PrimaryOffset(name, flags, map);
80a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Entry* primary = entry(primary_, primary_offset);
81a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  if (primary->key == name && primary->map == map) {
82a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    return primary->value;
83a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
84a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  int secondary_offset = SecondaryOffset(name, flags, primary_offset);
85a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Entry* secondary = entry(secondary_, secondary_offset);
86a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  if (secondary->key == name && secondary->map == map) {
87a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    return secondary->value;
88a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
89a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  return NULL;
90a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
91a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
92a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
93a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgvoid StubCache::Clear() {
94a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
95a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  for (int i = 0; i < kPrimaryTableSize; i++) {
96a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    primary_[i].key = isolate()->heap()->empty_string();
97a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    primary_[i].map = NULL;
98a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    primary_[i].value = empty;
99a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
100a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  for (int j = 0; j < kSecondaryTableSize; j++) {
101a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    secondary_[j].key = isolate()->heap()->empty_string();
102a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    secondary_[j].map = NULL;
103a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    secondary_[j].value = empty;
104a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
105a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
106a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
107a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
108a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgvoid StubCache::CollectMatchingMaps(SmallMapList* types, Handle<Name> name,
109a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org                                    Code::Flags flags,
110a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org                                    Handle<Context> native_context,
111a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org                                    Zone* zone) {
112a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  for (int i = 0; i < kPrimaryTableSize; i++) {
113a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    if (primary_[i].key == *name) {
114a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      Map* map = primary_[i].map;
115a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      // Map can be NULL, if the stub is constant function call
116a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      // with a primitive receiver.
117a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      if (map == NULL) continue;
118a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
119a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      int offset = PrimaryOffset(*name, flags, map);
120a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      if (entry(primary_, offset) == &primary_[i] &&
121a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org          !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
122a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org        types->AddMapIfMissing(Handle<Map>(map), zone);
123a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      }
124a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    }
125a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
126a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
127a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  for (int i = 0; i < kSecondaryTableSize; i++) {
128a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    if (secondary_[i].key == *name) {
129a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      Map* map = secondary_[i].map;
130a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      // Map can be NULL, if the stub is constant function call
131a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      // with a primitive receiver.
132a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      if (map == NULL) continue;
133a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
134a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      // Lookup in primary table and skip duplicates.
135a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      int primary_offset = PrimaryOffset(*name, flags, map);
136a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
137a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      // Lookup in secondary table and add matches.
138a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      int offset = SecondaryOffset(*name, flags, primary_offset);
139a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      if (entry(secondary_, offset) == &secondary_[i] &&
140a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org          !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
141a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org        types->AddMapIfMissing(Handle<Map>(map), zone);
142a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      }
143a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    }
144a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  }
145a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
146a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
147a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}  // namespace v8::internal
148