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

Side by Side Diff: src/stub-cache.cc

Issue 400523007: Cache IC handlers on the prototype's map if possible (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comment Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « src/stub-cache.h ('k') | src/x64/ic-x64.cc » ('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 2012 the V8 project authors. All rights reserved. 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 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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/arguments.h" 8 #include "src/arguments.h"
9 #include "src/ast.h" 9 #include "src/ast.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 15 matching lines...) Expand all
26 : isolate_(isolate) { } 26 : isolate_(isolate) { }
27 27
28 28
29 void StubCache::Initialize() { 29 void StubCache::Initialize() {
30 ASSERT(IsPowerOf2(kPrimaryTableSize)); 30 ASSERT(IsPowerOf2(kPrimaryTableSize));
31 ASSERT(IsPowerOf2(kSecondaryTableSize)); 31 ASSERT(IsPowerOf2(kSecondaryTableSize));
32 Clear(); 32 Clear();
33 } 33 }
34 34
35 35
36 Code* StubCache::Set(Name* name, Map* map, Code* code) { 36 static Code::Flags CommonStubCacheChecks(Name* name, Map* map,
37 // Get the flags from the code. 37 Code::Flags flags, Heap* heap) {
38 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags()); 38 flags = Code::RemoveTypeAndHolderFromFlags(flags);
39 39
40 // Validate that the name does not move on scavenge, and that we 40 // Validate that the name does not move on scavenge, and that we
41 // can use identity checks instead of structural equality checks. 41 // can use identity checks instead of structural equality checks.
42 ASSERT(!heap()->InNewSpace(name)); 42 ASSERT(!heap->InNewSpace(name));
43 ASSERT(name->IsUniqueName()); 43 ASSERT(name->IsUniqueName());
44 44
45 // The state bits are not important to the hash function because 45 // The state bits are not important to the hash function because
46 // the stub cache only contains monomorphic stubs. Make sure that 46 // the stub cache only contains monomorphic stubs. Make sure that
47 // the bits are the least significant so they will be the ones 47 // the bits are the least significant so they will be the ones
48 // masked out. 48 // masked out.
49 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC); 49 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
50 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1); 50 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
51 51
52 // Make sure that the code type is not included in the hash. 52 // Make sure that the code type and cache holder are not included in the hash.
53 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 53 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
54 ASSERT(Code::ExtractCacheHolderFromFlags(flags) == 0);
55
56 return flags;
57 }
58
59
60 Code* StubCache::Set(Name* name, Map* map, Code* code) {
61 Code::Flags flags = CommonStubCacheChecks(name, map, code->flags(), heap());
54 62
55 // Compute the primary entry. 63 // Compute the primary entry.
56 int primary_offset = PrimaryOffset(name, flags, map); 64 int primary_offset = PrimaryOffset(name, flags, map);
57 Entry* primary = entry(primary_, primary_offset); 65 Entry* primary = entry(primary_, primary_offset);
58 Code* old_code = primary->value; 66 Code* old_code = primary->value;
59 67
60 // If the primary entry has useful data in it, we retire it to the 68 // If the primary entry has useful data in it, we retire it to the
61 // secondary cache before overwriting it. 69 // secondary cache before overwriting it.
62 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { 70 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
63 Map* old_map = primary->map; 71 Map* old_map = primary->map;
64 Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags()); 72 Code::Flags old_flags =
73 Code::RemoveTypeAndHolderFromFlags(old_code->flags());
65 int seed = PrimaryOffset(primary->key, old_flags, old_map); 74 int seed = PrimaryOffset(primary->key, old_flags, old_map);
66 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); 75 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
67 Entry* secondary = entry(secondary_, secondary_offset); 76 Entry* secondary = entry(secondary_, secondary_offset);
68 *secondary = *primary; 77 *secondary = *primary;
69 } 78 }
70 79
71 // Update primary cache. 80 // Update primary cache.
72 primary->key = name; 81 primary->key = name;
73 primary->value = code; 82 primary->value = code;
74 primary->map = map; 83 primary->map = map;
75 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); 84 isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
76 return code; 85 return code;
77 } 86 }
78 87
79 88
80 Handle<Code> StubCache::FindIC(Handle<Name> name, 89 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) {
81 Handle<Map> stub_holder, 90 flags = CommonStubCacheChecks(name, map, flags, heap());
82 Code::Kind kind, 91 int primary_offset = PrimaryOffset(name, flags, map);
83 ExtraICState extra_state, 92 Entry* primary = entry(primary_, primary_offset);
84 InlineCacheHolderFlag cache_holder) { 93 if (primary->key == name && primary->map == map) {
94 return primary->value;
95 }
96 int secondary_offset = SecondaryOffset(name, flags, primary_offset);
97 Entry* secondary = entry(secondary_, secondary_offset);
98 if (secondary->key == name && secondary->map == map) {
99 return secondary->value;
100 }
101 return NULL;
102 }
103
104
105 Handle<Code> StubCache::FindIC(Handle<Name> name, Handle<Map> stub_holder,
106 Code::Kind kind, ExtraICState extra_state,
107 CacheHolderFlag cache_holder) {
85 Code::Flags flags = Code::ComputeMonomorphicFlags( 108 Code::Flags flags = Code::ComputeMonomorphicFlags(
86 kind, extra_state, cache_holder); 109 kind, extra_state, cache_holder);
87 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); 110 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
88 if (probe->IsCode()) return Handle<Code>::cast(probe); 111 if (probe->IsCode()) return Handle<Code>::cast(probe);
89 return Handle<Code>::null(); 112 return Handle<Code>::null();
90 } 113 }
91 114
92 115
93 Handle<Code> StubCache::FindHandler(Handle<Name> name, 116 Handle<Code> StubCache::FindHandler(Handle<Name> name, Handle<Map> stub_holder,
94 Handle<Map> stub_holder,
95 Code::Kind kind, 117 Code::Kind kind,
96 InlineCacheHolderFlag cache_holder, 118 CacheHolderFlag cache_holder,
97 Code::StubType type) { 119 Code::StubType type) {
98 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); 120 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder);
99 121
100 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); 122 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
101 if (probe->IsCode()) return Handle<Code>::cast(probe); 123 if (probe->IsCode()) return Handle<Code>::cast(probe);
102 return Handle<Code>::null(); 124 return Handle<Code>::null();
103 } 125 }
104 126
105 127
106 Handle<Code> StubCache::ComputeMonomorphicIC( 128 Handle<Code> StubCache::ComputeMonomorphicIC(
107 Code::Kind kind, 129 Code::Kind kind,
108 Handle<Name> name, 130 Handle<Name> name,
109 Handle<HeapType> type, 131 Handle<HeapType> type,
110 Handle<Code> handler, 132 Handle<Code> handler,
111 ExtraICState extra_ic_state) { 133 ExtraICState extra_ic_state) {
112 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); 134 CacheHolderFlag flag;
135 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate(), &flag);
113 136
114 Handle<Map> stub_holder;
115 Handle<Code> ic; 137 Handle<Code> ic;
116 // There are multiple string maps that all use the same prototype. That 138 // There are multiple string maps that all use the same prototype. That
117 // prototype cannot hold multiple handlers, one for each of the string maps, 139 // prototype cannot hold multiple handlers, one for each of the string maps,
118 // for a single name. Hence, turn off caching of the IC. 140 // for a single name. Hence, turn off caching of the IC.
119 bool can_be_cached = !type->Is(HeapType::String()); 141 bool can_be_cached = !type->Is(HeapType::String());
120 if (can_be_cached) { 142 if (can_be_cached) {
121 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
122 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); 143 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag);
123 if (!ic.is_null()) return ic; 144 if (!ic.is_null()) return ic;
124 } 145 }
125 146
126 if (kind == Code::LOAD_IC) { 147 if (kind == Code::LOAD_IC) {
127 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); 148 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag);
128 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 149 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
129 } else if (kind == Code::KEYED_LOAD_IC) { 150 } else if (kind == Code::KEYED_LOAD_IC) {
130 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); 151 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag);
131 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 152 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
132 } else if (kind == Code::STORE_IC) { 153 } else if (kind == Code::STORE_IC) {
133 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); 154 StoreStubCompiler ic_compiler(isolate(), extra_ic_state);
134 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 155 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
135 } else { 156 } else {
136 ASSERT(kind == Code::KEYED_STORE_IC); 157 ASSERT(kind == Code::KEYED_STORE_IC);
137 ASSERT(STANDARD_STORE == 158 ASSERT(STANDARD_STORE ==
138 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); 159 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state));
139 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); 160 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state);
140 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 161 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
141 } 162 }
142 163
143 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); 164 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic);
144 return ic; 165 return ic;
145 } 166 }
146 167
147 168
148 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, 169 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
149 Handle<HeapType> type) { 170 Handle<HeapType> type) {
150 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); 171 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate());
151 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); 172 if (receiver_map->prototype()->IsNull()) {
173 // TODO(jkummerow/verwaest): If there is no prototype and the property
174 // is nonexistent, introduce a builtin to handle this (fast properties
175 // -> return undefined, dictionary properties -> do negative lookup).
176 return Handle<Code>();
177 }
178 CacheHolderFlag flag;
179 Handle<Map> stub_holder_map =
180 IC::GetHandlerCacheHolder(*type, false, isolate(), &flag);
181
152 // If no dictionary mode objects are present in the prototype chain, the load 182 // If no dictionary mode objects are present in the prototype chain, the load
153 // nonexistent IC stub can be shared for all names for a given map and we use 183 // nonexistent IC stub can be shared for all names for a given map and we use
154 // the empty string for the map cache in that case. If there are dictionary 184 // the empty string for the map cache in that case. If there are dictionary
155 // mode objects involved, we need to do negative lookups in the stub and 185 // mode objects involved, we need to do negative lookups in the stub and
156 // therefore the stub will be specific to the name. 186 // therefore the stub will be specific to the name.
157 Handle<Map> current_map = stub_holder; 187 Handle<Name> cache_name =
158 Handle<Name> cache_name = current_map->is_dictionary_map() 188 receiver_map->is_dictionary_map()
159 ? name : Handle<Name>::cast(isolate()->factory()->nonexistent_symbol()); 189 ? name
160 Handle<Object> next(current_map->prototype(), isolate()); 190 : Handle<Name>::cast(isolate()->factory()->nonexistent_symbol());
161 Handle<JSObject> last = Handle<JSObject>::null(); 191 Handle<Map> current_map = stub_holder_map;
162 while (!next->IsNull()) { 192 Handle<JSObject> last(JSObject::cast(receiver_map->prototype()));
163 last = Handle<JSObject>::cast(next); 193 while (true) {
164 next = handle(current_map->prototype(), isolate());
165 current_map = handle(Handle<HeapObject>::cast(next)->map());
166 if (current_map->is_dictionary_map()) cache_name = name; 194 if (current_map->is_dictionary_map()) cache_name = name;
195 if (current_map->prototype()->IsNull()) break;
196 last = handle(JSObject::cast(current_map->prototype()));
197 current_map = handle(last->map());
167 } 198 }
168
169 // Compile the stub that is either shared for all names or 199 // Compile the stub that is either shared for all names or
170 // name specific if there are global objects involved. 200 // name specific if there are global objects involved.
171 Handle<Code> handler = FindHandler( 201 Handle<Code> handler =
172 cache_name, stub_holder, Code::LOAD_IC, flag, Code::FAST); 202 FindHandler(cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST);
173 if (!handler.is_null()) { 203 if (!handler.is_null()) {
174 return handler; 204 return handler;
175 } 205 }
176 206
177 LoadStubCompiler compiler(isolate_, kNoExtraICState, flag); 207 LoadStubCompiler compiler(isolate_, kNoExtraICState, flag);
178 handler = compiler.CompileLoadNonexistent(type, last, cache_name); 208 handler = compiler.CompileLoadNonexistent(type, last, cache_name);
179 Map::UpdateCodeCache(stub_holder, cache_name, handler); 209 Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
180 return handler; 210 return handler;
181 } 211 }
182 212
183 213
184 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { 214 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
185 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); 215 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
186 Handle<Name> name = 216 Handle<Name> name =
187 isolate()->factory()->KeyedLoadElementMonomorphic_string(); 217 isolate()->factory()->KeyedLoadElementMonomorphic_string();
188 218
189 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); 219 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
190 if (probe->IsCode()) return Handle<Code>::cast(probe); 220 if (probe->IsCode()) return Handle<Code>::cast(probe);
191 221
192 KeyedLoadStubCompiler compiler(isolate()); 222 KeyedLoadStubCompiler compiler(isolate());
193 Handle<Code> code = compiler.CompileLoadElement(receiver_map); 223 Handle<Code> code = compiler.CompileLoadElement(receiver_map);
194 224
195 Map::UpdateCodeCache(receiver_map, name, code); 225 Map::UpdateCodeCache(receiver_map, name, code);
196 return code; 226 return code;
197 } 227 }
198 228
199 229
200 Handle<Code> StubCache::ComputeKeyedStoreElement( 230 Handle<Code> StubCache::ComputeKeyedStoreElement(
201 Handle<Map> receiver_map, 231 Handle<Map> receiver_map,
202 StrictMode strict_mode, 232 StrictMode strict_mode,
203 KeyedAccessStoreMode store_mode) { 233 KeyedAccessStoreMode store_mode) {
204 ExtraICState extra_state = 234 ExtraICState extra_state =
205 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); 235 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode);
206 Code::Flags flags = Code::ComputeMonomorphicFlags( 236 Code::Flags flags =
207 Code::KEYED_STORE_IC, extra_state); 237 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state);
208 238
209 ASSERT(store_mode == STANDARD_STORE || 239 ASSERT(store_mode == STANDARD_STORE ||
210 store_mode == STORE_AND_GROW_NO_TRANSITION || 240 store_mode == STORE_AND_GROW_NO_TRANSITION ||
211 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 241 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
212 store_mode == STORE_NO_TRANSITION_HANDLE_COW); 242 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
213 243
214 Handle<String> name = 244 Handle<String> name =
215 isolate()->factory()->KeyedStoreElementMonomorphic_string(); 245 isolate()->factory()->KeyedStoreElementMonomorphic_string();
216 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); 246 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
217 if (probe->IsCode()) return Handle<Code>::cast(probe); 247 if (probe->IsCode()) return Handle<Code>::cast(probe);
(...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 Handle<FunctionTemplateInfo>( 1433 Handle<FunctionTemplateInfo>(
1404 FunctionTemplateInfo::cast(signature->receiver())); 1434 FunctionTemplateInfo::cast(signature->receiver()));
1405 } 1435 }
1406 } 1436 }
1407 1437
1408 is_simple_api_call_ = true; 1438 is_simple_api_call_ = true;
1409 } 1439 }
1410 1440
1411 1441
1412 } } // namespace v8::internal 1442 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/stub-cache.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698