OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/ic/ic-compiler.h" | 5 #include "src/ic/ic-compiler.h" |
6 | 6 |
7 #include "src/ic/handler-compiler.h" | 7 #include "src/ic/handler-compiler.h" |
8 #include "src/ic/ic-inl.h" | 8 #include "src/ic/ic-inl.h" |
9 #include "src/profiler/cpu-profiler.h" | 9 #include "src/profiler/cpu-profiler.h" |
10 | 10 |
(...skipping 15 matching lines...) Expand all Loading... |
26 | 26 |
27 | 27 |
28 bool PropertyICCompiler::IncludesNumberMap(MapHandleList* maps) { | 28 bool PropertyICCompiler::IncludesNumberMap(MapHandleList* maps) { |
29 for (int i = 0; i < maps->length(); ++i) { | 29 for (int i = 0; i < maps->length(); ++i) { |
30 if (maps->at(i)->instance_type() == HEAP_NUMBER_TYPE) return true; | 30 if (maps->at(i)->instance_type() == HEAP_NUMBER_TYPE) return true; |
31 } | 31 } |
32 return false; | 32 return false; |
33 } | 33 } |
34 | 34 |
35 | 35 |
36 Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<Map> map, | |
37 Handle<Code> handler, | |
38 Handle<Name> name, | |
39 IcCheckType check) { | |
40 MapHandleList maps(1); | |
41 CodeHandleList handlers(1); | |
42 maps.Add(map); | |
43 handlers.Add(handler); | |
44 Code::StubType stub_type = handler->type(); | |
45 return CompilePolymorphic(&maps, &handlers, name, stub_type, check); | |
46 } | |
47 | |
48 | |
49 Handle<Code> PropertyICCompiler::ComputeMonomorphic( | |
50 Code::Kind kind, Handle<Name> name, Handle<Map> map, Handle<Code> handler, | |
51 ExtraICState extra_ic_state) { | |
52 Isolate* isolate = name->GetIsolate(); | |
53 if (handler.is_identical_to(isolate->builtins()->LoadIC_Normal()) || | |
54 handler.is_identical_to(isolate->builtins()->LoadIC_Normal_Strong()) || | |
55 handler.is_identical_to(isolate->builtins()->StoreIC_Normal())) { | |
56 name = isolate->factory()->normal_ic_symbol(); | |
57 } | |
58 | |
59 CacheHolderFlag flag; | |
60 Handle<Map> stub_holder = IC::GetICCacheHolder(map, isolate, &flag); | |
61 if (kind == Code::KEYED_STORE_IC) { | |
62 // Always set the "property" bit. | |
63 extra_ic_state = | |
64 KeyedStoreIC::IcCheckTypeField::update(extra_ic_state, PROPERTY); | |
65 DCHECK(STANDARD_STORE == | |
66 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | |
67 } else if (kind == Code::KEYED_LOAD_IC) { | |
68 extra_ic_state = KeyedLoadIC::IcCheckTypeField::update(extra_ic_state, | |
69 PROPERTY); | |
70 } | |
71 | |
72 Handle<Code> ic; | |
73 // There are multiple string maps that all use the same prototype. That | |
74 // prototype cannot hold multiple handlers, one for each of the string maps, | |
75 // for a single name. Hence, turn off caching of the IC. | |
76 bool can_be_cached = map->instance_type() >= FIRST_NONSTRING_TYPE; | |
77 if (can_be_cached) { | |
78 ic = Find(name, stub_holder, kind, extra_ic_state, flag); | |
79 if (!ic.is_null()) return ic; | |
80 } | |
81 | |
82 PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag); | |
83 ic = ic_compiler.CompileMonomorphic(map, handler, name, PROPERTY); | |
84 | |
85 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | |
86 return ic; | |
87 } | |
88 | |
89 | |
90 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( | 36 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( |
91 Handle<Map> receiver_map, ExtraICState extra_ic_state) { | 37 Handle<Map> receiver_map, ExtraICState extra_ic_state) { |
92 Isolate* isolate = receiver_map->GetIsolate(); | 38 Isolate* isolate = receiver_map->GetIsolate(); |
93 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 39 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
94 ElementsKind elements_kind = receiver_map->elements_kind(); | 40 ElementsKind elements_kind = receiver_map->elements_kind(); |
95 | 41 |
96 // No need to check for an elements-free prototype chain here, the generated | 42 // No need to check for an elements-free prototype chain here, the generated |
97 // stub code needs to check that dynamically anyway. | 43 // stub code needs to check that dynamically anyway. |
98 bool convert_hole_to_undefined = | 44 bool convert_hole_to_undefined = |
99 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && | 45 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 77 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
132 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 78 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
133 | 79 |
134 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 80 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
135 Handle<Code> code = | 81 Handle<Code> code = |
136 compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode); | 82 compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode); |
137 return code; | 83 return code; |
138 } | 84 } |
139 | 85 |
140 | 86 |
141 Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphic( | |
142 Handle<Map> receiver_map, LanguageMode language_mode, | |
143 KeyedAccessStoreMode store_mode) { | |
144 Isolate* isolate = receiver_map->GetIsolate(); | |
145 ExtraICState extra_state = | |
146 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode); | |
147 Code::Flags flags = | |
148 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); | |
149 | |
150 DCHECK(store_mode == STANDARD_STORE || | |
151 store_mode == STORE_AND_GROW_NO_TRANSITION || | |
152 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | |
153 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | |
154 | |
155 Handle<String> name = isolate->factory()->KeyedStoreMonomorphic_string(); | |
156 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | |
157 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
158 | |
159 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | |
160 Handle<Code> code = | |
161 compiler.CompileKeyedStoreMonomorphic(receiver_map, store_mode); | |
162 | |
163 Map::UpdateCodeCache(receiver_map, name, code); | |
164 DCHECK(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) == | |
165 store_mode); | |
166 return code; | |
167 } | |
168 | |
169 | |
170 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, | 87 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, |
171 ExtraICState state) { | 88 ExtraICState state) { |
172 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 89 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
173 UnseededNumberDictionary* dictionary = | 90 UnseededNumberDictionary* dictionary = |
174 isolate->heap()->non_monomorphic_cache(); | 91 isolate->heap()->non_monomorphic_cache(); |
175 int entry = dictionary->FindEntry(isolate, flags); | 92 int entry = dictionary->FindEntry(isolate, flags); |
176 DCHECK(entry != -1); | 93 DCHECK(entry != -1); |
177 Object* code = dictionary->ValueAt(entry); | 94 Object* code = dictionary->ValueAt(entry); |
178 // This might be called during the marking phase of the collector | 95 // This might be called during the marking phase of the collector |
179 // hence the unchecked cast. | 96 // hence the unchecked cast. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 Handle<Code> ic = stub->GetCodeCopy(pattern); | 149 Handle<Code> ic = stub->GetCodeCopy(pattern); |
233 | 150 |
234 if (!receiver_map->is_dictionary_map()) { | 151 if (!receiver_map->is_dictionary_map()) { |
235 Map::UpdateCodeCache(receiver_map, name, ic); | 152 Map::UpdateCodeCache(receiver_map, name, ic); |
236 } | 153 } |
237 | 154 |
238 return ic; | 155 return ic; |
239 } | 156 } |
240 | 157 |
241 | 158 |
242 Handle<Code> PropertyICCompiler::ComputePolymorphic( | |
243 Code::Kind kind, MapHandleList* maps, CodeHandleList* handlers, | |
244 int valid_maps, Handle<Name> name, ExtraICState extra_ic_state) { | |
245 Handle<Code> handler = handlers->at(0); | |
246 Code::StubType type = valid_maps == 1 ? handler->type() : Code::NORMAL; | |
247 DCHECK(kind == Code::LOAD_IC || kind == Code::STORE_IC); | |
248 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); | |
249 return ic_compiler.CompilePolymorphic(maps, handlers, name, type, PROPERTY); | |
250 } | |
251 | |
252 | |
253 void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( | 159 void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( |
254 MapHandleList* receiver_maps, MapHandleList* transitioned_maps, | 160 MapHandleList* receiver_maps, MapHandleList* transitioned_maps, |
255 CodeHandleList* handlers, KeyedAccessStoreMode store_mode, | 161 CodeHandleList* handlers, KeyedAccessStoreMode store_mode, |
256 LanguageMode language_mode) { | 162 LanguageMode language_mode) { |
257 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 163 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
258 DCHECK(store_mode == STANDARD_STORE || | 164 DCHECK(store_mode == STANDARD_STORE || |
259 store_mode == STORE_AND_GROW_NO_TRANSITION || | 165 store_mode == STORE_AND_GROW_NO_TRANSITION || |
260 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 166 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
261 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 167 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
262 ExtraICState extra_state = | 168 ExtraICState extra_state = |
263 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode); | 169 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode); |
264 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 170 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
265 compiler.CompileKeyedStorePolymorphicHandlers( | 171 compiler.CompileKeyedStorePolymorphicHandlers( |
266 receiver_maps, transitioned_maps, handlers, store_mode); | 172 receiver_maps, transitioned_maps, handlers, store_mode); |
267 } | 173 } |
268 | 174 |
269 | 175 |
270 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( | |
271 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, | |
272 LanguageMode language_mode) { | |
273 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | |
274 DCHECK(store_mode == STANDARD_STORE || | |
275 store_mode == STORE_AND_GROW_NO_TRANSITION || | |
276 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | |
277 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | |
278 Handle<PolymorphicCodeCache> cache = | |
279 isolate->factory()->polymorphic_code_cache(); | |
280 ExtraICState extra_state = | |
281 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode); | |
282 Code::Flags flags = | |
283 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | |
284 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | |
285 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
286 | |
287 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | |
288 Handle<Code> code = | |
289 compiler.CompileKeyedStorePolymorphic(receiver_maps, store_mode); | |
290 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | |
291 return code; | |
292 } | |
293 | |
294 | |
295 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { | 176 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { |
296 LoadIC::GenerateInitialize(masm()); | 177 LoadIC::GenerateInitialize(masm()); |
297 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 178 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); |
298 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | 179 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |
299 return code; | 180 return code; |
300 } | 181 } |
301 | 182 |
302 | 183 |
303 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { | 184 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { |
304 StoreIC::GenerateInitialize(masm()); | 185 StoreIC::GenerateInitialize(masm()); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 StoreElementStub(isolate(), elements_kind, store_mode).GetCode(); | 268 StoreElementStub(isolate(), elements_kind, store_mode).GetCode(); |
388 } | 269 } |
389 } | 270 } |
390 DCHECK(!cached_stub.is_null()); | 271 DCHECK(!cached_stub.is_null()); |
391 handlers->Add(cached_stub); | 272 handlers->Add(cached_stub); |
392 transitioned_maps->Add(transitioned_map); | 273 transitioned_maps->Add(transitioned_map); |
393 } | 274 } |
394 } | 275 } |
395 | 276 |
396 | 277 |
397 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( | |
398 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode) { | |
399 // Collect MONOMORPHIC stubs for all |receiver_maps|. | |
400 CodeHandleList handlers(receiver_maps->length()); | |
401 MapHandleList transitioned_maps(receiver_maps->length()); | |
402 CompileKeyedStorePolymorphicHandlers(receiver_maps, &transitioned_maps, | |
403 &handlers, store_mode); | |
404 | |
405 Handle<Code> code = CompileKeyedStorePolymorphic(receiver_maps, &handlers, | |
406 &transitioned_maps); | |
407 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); | |
408 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, 0)); | |
409 return code; | |
410 } | |
411 | |
412 | |
413 #define __ ACCESS_MASM(masm()) | 278 #define __ ACCESS_MASM(masm()) |
414 | 279 |
415 | 280 |
416 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler( | 281 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler( |
417 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { | 282 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { |
418 ElementsKind elements_kind = receiver_map->elements_kind(); | 283 ElementsKind elements_kind = receiver_map->elements_kind(); |
419 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 284 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
420 Handle<Code> stub; | 285 Handle<Code> stub; |
421 if (receiver_map->has_sloppy_arguments_elements()) { | 286 if (receiver_map->has_sloppy_arguments_elements()) { |
422 stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode(); | 287 stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode(); |
(...skipping 20 matching lines...) Expand all Loading... |
443 | 308 |
444 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); | 309 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); |
445 | 310 |
446 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); | 311 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); |
447 } | 312 } |
448 | 313 |
449 | 314 |
450 #undef __ | 315 #undef __ |
451 } // namespace internal | 316 } // namespace internal |
452 } // namespace v8 | 317 } // namespace v8 |
OLD | NEW |