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