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/v8.h" | 5 #include "src/v8.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/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
10 | 10 |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 | 15 |
16 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, | 16 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, |
17 Handle<Map> stub_holder, Code::Kind kind, | 17 Handle<Map> stub_holder, Code::Kind kind, |
18 ExtraICState extra_state, | 18 ExtraICState extra_state, |
19 CacheHolderFlag cache_holder) { | 19 CacheHolderFlag cache_holder) { |
20 Code::Flags flags = | 20 Code::Flags flags = |
21 Code::ComputeMonomorphicFlags(kind, extra_state, cache_holder); | 21 Code::ComputeMonomorphicFlags(kind, extra_state, cache_holder); |
22 Object* probe = stub_holder->FindInCodeCache(*name, flags); | 22 Object* probe = stub_holder->FindInCodeCache(*name, flags); |
23 if (probe->IsCode()) return handle(Code::cast(probe)); | 23 if (probe->IsCode()) return handle(Code::cast(probe)); |
24 return Handle<Code>::null(); | 24 return Handle<Code>::null(); |
25 } | 25 } |
26 | 26 |
27 | 27 |
28 bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) { | 28 bool PropertyICCompiler::IncludesNumberMap(MapHandleList* maps) { |
29 for (int i = 0; i < types->length(); ++i) { | 29 for (int i = 0; i < maps->length(); ++i) { |
30 if (types->at(i)->Is(HeapType::Number())) 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<HeapType> type, | 36 Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<Map> map, |
37 Handle<Code> handler, | 37 Handle<Code> handler, |
38 Handle<Name> name, | 38 Handle<Name> name, |
39 IcCheckType check) { | 39 IcCheckType check) { |
40 TypeHandleList types(1); | 40 MapHandleList maps(1); |
41 CodeHandleList handlers(1); | 41 CodeHandleList handlers(1); |
42 types.Add(type); | 42 maps.Add(map); |
43 handlers.Add(handler); | 43 handlers.Add(handler); |
44 Code::StubType stub_type = handler->type(); | 44 Code::StubType stub_type = handler->type(); |
45 return CompilePolymorphic(&types, &handlers, name, stub_type, check); | 45 return CompilePolymorphic(&maps, &handlers, name, stub_type, check); |
46 } | 46 } |
47 | 47 |
48 | 48 |
49 Handle<Code> PropertyICCompiler::ComputeMonomorphic( | 49 Handle<Code> PropertyICCompiler::ComputeMonomorphic( |
50 Code::Kind kind, Handle<Name> name, Handle<HeapType> type, | 50 Code::Kind kind, Handle<Name> name, Handle<Map> map, Handle<Code> handler, |
51 Handle<Code> handler, ExtraICState extra_ic_state) { | 51 ExtraICState extra_ic_state) { |
52 Isolate* isolate = name->GetIsolate(); | 52 Isolate* isolate = name->GetIsolate(); |
53 if (handler.is_identical_to(isolate->builtins()->LoadIC_Normal()) || | 53 if (handler.is_identical_to(isolate->builtins()->LoadIC_Normal()) || |
54 handler.is_identical_to(isolate->builtins()->StoreIC_Normal())) { | 54 handler.is_identical_to(isolate->builtins()->StoreIC_Normal())) { |
55 name = isolate->factory()->normal_ic_symbol(); | 55 name = isolate->factory()->normal_ic_symbol(); |
56 } | 56 } |
57 | 57 |
58 CacheHolderFlag flag; | 58 CacheHolderFlag flag; |
59 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag); | 59 Handle<Map> stub_holder = IC::GetICCacheHolder(map, isolate, &flag); |
60 if (kind == Code::KEYED_STORE_IC) { | 60 if (kind == Code::KEYED_STORE_IC) { |
61 // Always set the "property" bit. | 61 // Always set the "property" bit. |
62 extra_ic_state = | 62 extra_ic_state = |
63 KeyedStoreIC::IcCheckTypeField::update(extra_ic_state, PROPERTY); | 63 KeyedStoreIC::IcCheckTypeField::update(extra_ic_state, PROPERTY); |
64 DCHECK(STANDARD_STORE == | 64 DCHECK(STANDARD_STORE == |
65 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | 65 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); |
66 } else if (kind == Code::KEYED_LOAD_IC) { | 66 } else if (kind == Code::KEYED_LOAD_IC) { |
67 extra_ic_state = KeyedLoadIC::IcCheckTypeField::update(extra_ic_state, | 67 extra_ic_state = KeyedLoadIC::IcCheckTypeField::update(extra_ic_state, |
68 PROPERTY); | 68 PROPERTY); |
69 } | 69 } |
70 | 70 |
71 Handle<Code> ic; | 71 Handle<Code> ic; |
72 // There are multiple string maps that all use the same prototype. That | 72 // There are multiple string maps that all use the same prototype. That |
73 // prototype cannot hold multiple handlers, one for each of the string maps, | 73 // prototype cannot hold multiple handlers, one for each of the string maps, |
74 // for a single name. Hence, turn off caching of the IC. | 74 // for a single name. Hence, turn off caching of the IC. |
75 bool can_be_cached = !type->Is(HeapType::String()); | 75 bool can_be_cached = map->instance_type() >= FIRST_NONSTRING_TYPE; |
76 if (can_be_cached) { | 76 if (can_be_cached) { |
77 ic = Find(name, stub_holder, kind, extra_ic_state, flag); | 77 ic = Find(name, stub_holder, kind, extra_ic_state, flag); |
78 if (!ic.is_null()) return ic; | 78 if (!ic.is_null()) return ic; |
79 } | 79 } |
80 | 80 |
81 PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag); | 81 PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag); |
82 ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY); | 82 ic = ic_compiler.CompileMonomorphic(map, handler, name, PROPERTY); |
83 | 83 |
84 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 84 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
85 return ic; | 85 return ic; |
86 } | 86 } |
87 | 87 |
88 | 88 |
89 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic( | 89 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic( |
90 Handle<Map> receiver_map) { | 90 Handle<Map> receiver_map) { |
91 Isolate* isolate = receiver_map->GetIsolate(); | 91 Isolate* isolate = receiver_map->GetIsolate(); |
92 DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT); | 92 DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT); |
93 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 93 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
94 Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string(); | 94 Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string(); |
95 | 95 |
96 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | 96 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
97 if (probe->IsCode()) return Handle<Code>::cast(probe); | 97 if (probe->IsCode()) return Handle<Code>::cast(probe); |
98 | 98 |
99 Handle<Code> stub = ComputeKeyedLoadMonomorphicHandler(receiver_map); | 99 Handle<Code> stub = ComputeKeyedLoadMonomorphicHandler(receiver_map); |
100 PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); | 100 PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); |
101 Handle<Code> code = | 101 Handle<Code> code = compiler.CompileMonomorphic( |
102 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate), stub, | 102 receiver_map, stub, isolate->factory()->empty_string(), ELEMENT); |
103 isolate->factory()->empty_string(), ELEMENT); | |
104 | 103 |
105 Map::UpdateCodeCache(receiver_map, name, code); | 104 Map::UpdateCodeCache(receiver_map, name, code); |
106 return code; | 105 return code; |
107 } | 106 } |
108 | 107 |
109 | 108 |
110 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( | 109 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler( |
111 Handle<Map> receiver_map) { | 110 Handle<Map> receiver_map) { |
112 Isolate* isolate = receiver_map->GetIsolate(); | 111 Isolate* isolate = receiver_map->GetIsolate(); |
113 ElementsKind elements_kind = receiver_map->elements_kind(); | 112 ElementsKind elements_kind = receiver_map->elements_kind(); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 Handle<Code> ic = stub->GetCodeCopy(pattern); | 248 Handle<Code> ic = stub->GetCodeCopy(pattern); |
250 | 249 |
251 if (!receiver_map->is_dictionary_map()) { | 250 if (!receiver_map->is_dictionary_map()) { |
252 Map::UpdateCodeCache(receiver_map, name, ic); | 251 Map::UpdateCodeCache(receiver_map, name, ic); |
253 } | 252 } |
254 | 253 |
255 return ic; | 254 return ic; |
256 } | 255 } |
257 | 256 |
258 | 257 |
259 // TODO(verwaest): Change this method so it takes in a TypeHandleList. | |
260 Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic( | 258 Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic( |
261 MapHandleList* receiver_maps) { | 259 MapHandleList* receiver_maps) { |
262 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 260 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
263 DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT); | 261 DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT); |
264 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 262 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
265 Handle<PolymorphicCodeCache> cache = | 263 Handle<PolymorphicCodeCache> cache = |
266 isolate->factory()->polymorphic_code_cache(); | 264 isolate->factory()->polymorphic_code_cache(); |
267 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 265 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
268 if (probe->IsCode()) return Handle<Code>::cast(probe); | 266 if (probe->IsCode()) return Handle<Code>::cast(probe); |
269 | 267 |
270 TypeHandleList types(receiver_maps->length()); | |
271 for (int i = 0; i < receiver_maps->length(); i++) { | |
272 types.Add(HeapType::Class(receiver_maps->at(i), isolate)); | |
273 } | |
274 CodeHandleList handlers(receiver_maps->length()); | 268 CodeHandleList handlers(receiver_maps->length()); |
275 ElementHandlerCompiler compiler(isolate); | 269 ElementHandlerCompiler compiler(isolate); |
276 compiler.CompileElementHandlers(receiver_maps, &handlers); | 270 compiler.CompileElementHandlers(receiver_maps, &handlers); |
277 PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); | 271 PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); |
278 Handle<Code> code = ic_compiler.CompilePolymorphic( | 272 Handle<Code> code = ic_compiler.CompilePolymorphic( |
279 &types, &handlers, isolate->factory()->empty_string(), Code::NORMAL, | 273 receiver_maps, &handlers, isolate->factory()->empty_string(), |
280 ELEMENT); | 274 Code::NORMAL, ELEMENT); |
281 | 275 |
282 isolate->counters()->keyed_load_polymorphic_stubs()->Increment(); | 276 isolate->counters()->keyed_load_polymorphic_stubs()->Increment(); |
283 | 277 |
284 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 278 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
285 return code; | 279 return code; |
286 } | 280 } |
287 | 281 |
288 | 282 |
289 Handle<Code> PropertyICCompiler::ComputePolymorphic( | 283 Handle<Code> PropertyICCompiler::ComputePolymorphic( |
290 Code::Kind kind, TypeHandleList* types, CodeHandleList* handlers, | 284 Code::Kind kind, MapHandleList* maps, CodeHandleList* handlers, |
291 int valid_types, Handle<Name> name, ExtraICState extra_ic_state) { | 285 int valid_maps, Handle<Name> name, ExtraICState extra_ic_state) { |
292 Handle<Code> handler = handlers->at(0); | 286 Handle<Code> handler = handlers->at(0); |
293 Code::StubType type = valid_types == 1 ? handler->type() : Code::NORMAL; | 287 Code::StubType type = valid_maps == 1 ? handler->type() : Code::NORMAL; |
294 DCHECK(kind == Code::LOAD_IC || kind == Code::STORE_IC); | 288 DCHECK(kind == Code::LOAD_IC || kind == Code::STORE_IC); |
295 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); | 289 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); |
296 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); | 290 return ic_compiler.CompilePolymorphic(maps, handlers, name, type, PROPERTY); |
297 } | 291 } |
298 | 292 |
299 | 293 |
300 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( | 294 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( |
301 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, | 295 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, |
302 LanguageMode language_mode) { | 296 LanguageMode language_mode) { |
303 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 297 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
304 DCHECK(store_mode == STANDARD_STORE || | 298 DCHECK(store_mode == STANDARD_STORE || |
305 store_mode == STORE_AND_GROW_NO_TRANSITION || | 299 store_mode == STORE_AND_GROW_NO_TRANSITION || |
306 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 300 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 | 454 |
461 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); | 455 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); |
462 | 456 |
463 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); | 457 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); |
464 } | 458 } |
465 | 459 |
466 | 460 |
467 #undef __ | 461 #undef __ |
468 } | 462 } |
469 } // namespace v8::internal | 463 } // namespace v8::internal |
OLD | NEW |