| 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 |