| OLD | NEW |
| 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/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 | 490 |
| 491 void IC::Clear(Isolate* isolate, Address address, | 491 void IC::Clear(Isolate* isolate, Address address, |
| 492 ConstantPoolArray* constant_pool) { | 492 ConstantPoolArray* constant_pool) { |
| 493 Code* target = GetTargetAtAddress(address, constant_pool); | 493 Code* target = GetTargetAtAddress(address, constant_pool); |
| 494 | 494 |
| 495 // Don't clear debug break inline cache as it will remove the break point. | 495 // Don't clear debug break inline cache as it will remove the break point. |
| 496 if (target->is_debug_stub()) return; | 496 if (target->is_debug_stub()) return; |
| 497 | 497 |
| 498 switch (target->kind()) { | 498 switch (target->kind()) { |
| 499 case Code::LOAD_IC: | 499 case Code::LOAD_IC: |
| 500 if (FLAG_vector_ics) return; | |
| 501 return LoadIC::Clear(isolate, address, target, constant_pool); | |
| 502 case Code::KEYED_LOAD_IC: | 500 case Code::KEYED_LOAD_IC: |
| 503 if (FLAG_vector_ics) return; | 501 return; |
| 504 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | |
| 505 case Code::STORE_IC: | 502 case Code::STORE_IC: |
| 506 return StoreIC::Clear(isolate, address, target, constant_pool); | 503 return StoreIC::Clear(isolate, address, target, constant_pool); |
| 507 case Code::KEYED_STORE_IC: | 504 case Code::KEYED_STORE_IC: |
| 508 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 505 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
| 509 case Code::COMPARE_IC: | 506 case Code::COMPARE_IC: |
| 510 return CompareIC::Clear(isolate, address, target, constant_pool); | 507 return CompareIC::Clear(isolate, address, target, constant_pool); |
| 511 case Code::COMPARE_NIL_IC: | 508 case Code::COMPARE_NIL_IC: |
| 512 return CompareNilIC::Clear(address, target, constant_pool); | 509 return CompareNilIC::Clear(address, target, constant_pool); |
| 513 case Code::CALL_IC: // CallICs are vector-based and cleared differently. | 510 case Code::CALL_IC: // CallICs are vector-based and cleared differently. |
| 514 case Code::BINARY_OP_IC: | 511 case Code::BINARY_OP_IC: |
| 515 case Code::TO_BOOLEAN_IC: | 512 case Code::TO_BOOLEAN_IC: |
| 516 // Clearing these is tricky and does not | 513 // Clearing these is tricky and does not |
| 517 // make any performance difference. | 514 // make any performance difference. |
| 518 return; | 515 return; |
| 519 default: | 516 default: |
| 520 UNREACHABLE(); | 517 UNREACHABLE(); |
| 521 } | 518 } |
| 522 } | 519 } |
| 523 | 520 |
| 524 | 521 |
| 525 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | |
| 526 ConstantPoolArray* constant_pool) { | |
| 527 DCHECK(!FLAG_vector_ics); | |
| 528 if (IsCleared(target)) return; | |
| 529 | |
| 530 // Make sure to also clear the map used in inline fast cases. If we | |
| 531 // do not clear these maps, cached code can keep objects alive | |
| 532 // through the embedded maps. | |
| 533 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | |
| 534 } | |
| 535 | |
| 536 | |
| 537 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { | 522 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) { |
| 538 if (IsCleared(nexus)) return; | 523 if (IsCleared(nexus)) return; |
| 539 // Make sure to also clear the map used in inline fast cases. If we | 524 // Make sure to also clear the map used in inline fast cases. If we |
| 540 // do not clear these maps, cached code can keep objects alive | 525 // do not clear these maps, cached code can keep objects alive |
| 541 // through the embedded maps. | 526 // through the embedded maps. |
| 542 State state = nexus->StateFromFeedback(); | 527 State state = nexus->StateFromFeedback(); |
| 543 nexus->ConfigurePremonomorphic(); | 528 nexus->ConfigurePremonomorphic(); |
| 544 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 529 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); |
| 545 } | 530 } |
| 546 | 531 |
| 547 | 532 |
| 548 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 533 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { |
| 549 // Determine our state. | 534 // Determine our state. |
| 550 Object* feedback = nexus->vector()->Get(nexus->slot()); | 535 Object* feedback = nexus->vector()->Get(nexus->slot()); |
| 551 State state = nexus->StateFromFeedback(); | 536 State state = nexus->StateFromFeedback(); |
| 552 | 537 |
| 553 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 538 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
| 554 nexus->ConfigureUninitialized(); | 539 nexus->ConfigureUninitialized(); |
| 555 // The change in state must be processed. | 540 // The change in state must be processed. |
| 556 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 541 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); |
| 557 } | 542 } |
| 558 } | 543 } |
| 559 | 544 |
| 560 | 545 |
| 561 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | |
| 562 ConstantPoolArray* constant_pool) { | |
| 563 DCHECK(!FLAG_vector_ics); | |
| 564 if (IsCleared(target)) return; | |
| 565 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, | |
| 566 target->extra_ic_state()); | |
| 567 SetTargetAtAddress(address, code, constant_pool); | |
| 568 } | |
| 569 | |
| 570 | |
| 571 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { | 546 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) { |
| 572 if (IsCleared(nexus)) return; | 547 if (IsCleared(nexus)) return; |
| 573 State state = nexus->StateFromFeedback(); | 548 State state = nexus->StateFromFeedback(); |
| 574 nexus->ConfigurePremonomorphic(); | 549 nexus->ConfigurePremonomorphic(); |
| 575 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); | 550 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC); |
| 576 } | 551 } |
| 577 | 552 |
| 578 | 553 |
| 579 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, | 554 void StoreIC::Clear(Isolate* isolate, Address address, Code* target, |
| 580 ConstantPoolArray* constant_pool) { | 555 ConstantPoolArray* constant_pool) { |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 case DEFAULT: | 910 case DEFAULT: |
| 936 case GENERIC: | 911 case GENERIC: |
| 937 UNREACHABLE(); | 912 UNREACHABLE(); |
| 938 break; | 913 break; |
| 939 } | 914 } |
| 940 } | 915 } |
| 941 | 916 |
| 942 | 917 |
| 943 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 918 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
| 944 ExtraICState extra_state) { | 919 ExtraICState extra_state) { |
| 945 if (FLAG_vector_ics) { | 920 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); |
| 946 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); | |
| 947 } | |
| 948 | |
| 949 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | |
| 950 } | |
| 951 | |
| 952 | |
| 953 Handle<Code> LoadIC::load_global(Isolate* isolate, Handle<GlobalObject> global, | |
| 954 Handle<String> name) { | |
| 955 // This special IC doesn't work with vector ics. | |
| 956 DCHECK(!FLAG_vector_ics); | |
| 957 | |
| 958 Handle<ScriptContextTable> script_contexts( | |
| 959 global->native_context()->script_context_table()); | |
| 960 | |
| 961 ScriptContextTable::LookupResult lookup_result; | |
| 962 if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) { | |
| 963 return initialize_stub(isolate, LoadICState(CONTEXTUAL).GetExtraICState()); | |
| 964 } | |
| 965 | |
| 966 Handle<Map> global_map(global->map()); | |
| 967 Handle<Code> handler = PropertyHandlerCompiler::Find( | |
| 968 name, global_map, Code::LOAD_IC, kCacheOnReceiver, Code::NORMAL); | |
| 969 if (handler.is_null()) { | |
| 970 LookupIterator it(global, name); | |
| 971 if (!it.IsFound() || !it.GetHolder<JSObject>().is_identical_to(global) || | |
| 972 it.state() != LookupIterator::DATA) { | |
| 973 return initialize_stub(isolate, | |
| 974 LoadICState(CONTEXTUAL).GetExtraICState()); | |
| 975 } | |
| 976 NamedLoadHandlerCompiler compiler(isolate, global_map, global, | |
| 977 kCacheOnReceiver); | |
| 978 Handle<PropertyCell> cell = it.GetPropertyCell(); | |
| 979 handler = compiler.CompileLoadGlobal(cell, name, it.IsConfigurable()); | |
| 980 Map::UpdateCodeCache(global_map, name, handler); | |
| 981 } | |
| 982 return PropertyICCompiler::ComputeMonomorphic( | |
| 983 Code::LOAD_IC, name, handle(global->map()), handler, | |
| 984 LoadICState(CONTEXTUAL).GetExtraICState()); | |
| 985 } | 921 } |
| 986 | 922 |
| 987 | 923 |
| 988 Handle<Code> LoadIC::initialize_stub_in_optimized_code( | 924 Handle<Code> LoadIC::initialize_stub_in_optimized_code( |
| 989 Isolate* isolate, ExtraICState extra_state, State initialization_state) { | 925 Isolate* isolate, ExtraICState extra_state, State initialization_state) { |
| 990 if (FLAG_vector_ics) { | 926 return VectorRawLoadStub(isolate, LoadICState(extra_state)).GetCode(); |
| 991 return VectorRawLoadStub(isolate, LoadICState(extra_state)).GetCode(); | |
| 992 } | |
| 993 return PropertyICCompiler::ComputeLoad(isolate, initialization_state, | |
| 994 extra_state); | |
| 995 } | 927 } |
| 996 | 928 |
| 997 | 929 |
| 998 Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) { | 930 Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) { |
| 999 if (FLAG_vector_ics) { | 931 return KeyedLoadICTrampolineStub(isolate).GetCode(); |
| 1000 return KeyedLoadICTrampolineStub(isolate).GetCode(); | |
| 1001 } | |
| 1002 | |
| 1003 return isolate->builtins()->KeyedLoadIC_Initialize(); | |
| 1004 } | 932 } |
| 1005 | 933 |
| 1006 | 934 |
| 1007 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( | 935 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code( |
| 1008 Isolate* isolate, State initialization_state) { | 936 Isolate* isolate, State initialization_state) { |
| 1009 if (FLAG_vector_ics && initialization_state != MEGAMORPHIC) { | 937 if (initialization_state != MEGAMORPHIC) { |
| 1010 return VectorRawKeyedLoadStub(isolate).GetCode(); | 938 return VectorRawKeyedLoadStub(isolate).GetCode(); |
| 1011 } | 939 } |
| 1012 switch (initialization_state) { | 940 switch (initialization_state) { |
| 1013 case UNINITIALIZED: | 941 case UNINITIALIZED: |
| 1014 return isolate->builtins()->KeyedLoadIC_Initialize(); | 942 return isolate->builtins()->KeyedLoadIC_Initialize(); |
| 1015 case PREMONOMORPHIC: | |
| 1016 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); | |
| 1017 case MEGAMORPHIC: | 943 case MEGAMORPHIC: |
| 1018 return isolate->builtins()->KeyedLoadIC_Megamorphic(); | 944 return isolate->builtins()->KeyedLoadIC_Megamorphic(); |
| 1019 default: | 945 default: |
| 1020 UNREACHABLE(); | 946 UNREACHABLE(); |
| 1021 } | 947 } |
| 1022 return Handle<Code>(); | 948 return Handle<Code>(); |
| 1023 } | 949 } |
| 1024 | 950 |
| 1025 | 951 |
| 1026 Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, | 952 Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1040 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() | 966 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict() |
| 1041 : isolate->builtins()->KeyedStoreIC_Megamorphic(); | 967 : isolate->builtins()->KeyedStoreIC_Megamorphic(); |
| 1042 default: | 968 default: |
| 1043 UNREACHABLE(); | 969 UNREACHABLE(); |
| 1044 } | 970 } |
| 1045 return Handle<Code>(); | 971 return Handle<Code>(); |
| 1046 } | 972 } |
| 1047 | 973 |
| 1048 | 974 |
| 1049 Handle<Code> LoadIC::megamorphic_stub() { | 975 Handle<Code> LoadIC::megamorphic_stub() { |
| 1050 if (kind() == Code::LOAD_IC) { | 976 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 1051 MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); | 977 return KeyedLoadIC::ChooseMegamorphicStub(isolate()); |
| 1052 return stub.GetCode(); | |
| 1053 } else { | |
| 1054 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | |
| 1055 return KeyedLoadIC::ChooseMegamorphicStub(isolate()); | |
| 1056 } | |
| 1057 } | 978 } |
| 1058 | 979 |
| 1059 | 980 |
| 1060 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | |
| 1061 ExtraICState extra_state) { | |
| 1062 DCHECK(!FLAG_vector_ics); | |
| 1063 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | |
| 1064 } | |
| 1065 | |
| 1066 | |
| 1067 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { | |
| 1068 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); | |
| 1069 } | |
| 1070 | |
| 1071 | |
| 1072 Handle<Code> LoadIC::pre_monomorphic_stub() const { | |
| 1073 if (kind() == Code::LOAD_IC) { | |
| 1074 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); | |
| 1075 } else { | |
| 1076 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | |
| 1077 return KeyedLoadIC::pre_monomorphic_stub(isolate()); | |
| 1078 } | |
| 1079 } | |
| 1080 | |
| 1081 | |
| 1082 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 981 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
| 1083 LoadFieldStub stub(isolate(), index); | 982 LoadFieldStub stub(isolate(), index); |
| 1084 return stub.GetCode(); | 983 return stub.GetCode(); |
| 1085 } | 984 } |
| 1086 | 985 |
| 1087 | 986 |
| 1088 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 987 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
| 1089 if (state() == UNINITIALIZED) { | 988 if (state() == UNINITIALIZED) { |
| 1090 // This is the first time we execute this inline cache. Set the target to | 989 // This is the first time we execute this inline cache. Set the target to |
| 1091 // the pre monomorphic stub to delay setting the monomorphic state. | 990 // the pre monomorphic stub to delay setting the monomorphic state. |
| 1092 if (UseVector()) { | 991 ConfigureVectorState(PREMONOMORPHIC); |
| 1093 ConfigureVectorState(PREMONOMORPHIC); | |
| 1094 } else { | |
| 1095 set_target(*pre_monomorphic_stub()); | |
| 1096 } | |
| 1097 TRACE_IC("LoadIC", lookup->name()); | 992 TRACE_IC("LoadIC", lookup->name()); |
| 1098 return; | 993 return; |
| 1099 } | 994 } |
| 1100 | 995 |
| 1101 Handle<Code> code; | 996 Handle<Code> code; |
| 1102 if (lookup->state() == LookupIterator::JSPROXY || | 997 if (lookup->state() == LookupIterator::JSPROXY || |
| 1103 lookup->state() == LookupIterator::ACCESS_CHECK) { | 998 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 1104 code = slow_stub(); | 999 code = slow_stub(); |
| 1105 } else if (!lookup->IsFound()) { | 1000 } else if (!lookup->IsFound()) { |
| 1106 if (kind() == Code::LOAD_IC) { | 1001 if (kind() == Code::LOAD_IC) { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 | 1249 |
| 1355 | 1250 |
| 1356 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { | 1251 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) { |
| 1357 Handle<Code> null_handle; | 1252 Handle<Code> null_handle; |
| 1358 Handle<Map> receiver_map(receiver->map(), isolate()); | 1253 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1359 MapHandleList target_receiver_maps; | 1254 MapHandleList target_receiver_maps; |
| 1360 TargetMaps(&target_receiver_maps); | 1255 TargetMaps(&target_receiver_maps); |
| 1361 | 1256 |
| 1362 | 1257 |
| 1363 if (target_receiver_maps.length() == 0) { | 1258 if (target_receiver_maps.length() == 0) { |
| 1364 if (FLAG_vector_ics) { | 1259 Handle<Code> handler = |
| 1365 Handle<Code> handler = | 1260 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); |
| 1366 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | 1261 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); |
| 1367 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); | 1262 return null_handle; |
| 1368 return null_handle; | |
| 1369 } | |
| 1370 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | |
| 1371 } | 1263 } |
| 1372 | 1264 |
| 1373 // The first time a receiver is seen that is a transitioned version of the | 1265 // The first time a receiver is seen that is a transitioned version of the |
| 1374 // previous monomorphic receiver type, assume the new ElementsKind is the | 1266 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1375 // monomorphic type. This benefits global arrays that only transition | 1267 // monomorphic type. This benefits global arrays that only transition |
| 1376 // once, and all call sites accessing them are faster if they remain | 1268 // once, and all call sites accessing them are faster if they remain |
| 1377 // monomorphic. If this optimistic assumption is not true, the IC will | 1269 // monomorphic. If this optimistic assumption is not true, the IC will |
| 1378 // miss again and it will become polymorphic and support both the | 1270 // miss again and it will become polymorphic and support both the |
| 1379 // untransitioned and transitioned maps. | 1271 // untransitioned and transitioned maps. |
| 1380 if (state() == MONOMORPHIC && !receiver->IsString() && | 1272 if (state() == MONOMORPHIC && !receiver->IsString() && |
| 1381 IsMoreGeneralElementsKindTransition( | 1273 IsMoreGeneralElementsKindTransition( |
| 1382 target_receiver_maps.at(0)->elements_kind(), | 1274 target_receiver_maps.at(0)->elements_kind(), |
| 1383 Handle<JSObject>::cast(receiver)->GetElementsKind())) { | 1275 Handle<JSObject>::cast(receiver)->GetElementsKind())) { |
| 1384 if (FLAG_vector_ics) { | 1276 Handle<Code> handler = |
| 1385 Handle<Code> handler = | 1277 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); |
| 1386 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map); | 1278 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); |
| 1387 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); | 1279 return null_handle; |
| 1388 return null_handle; | |
| 1389 } | |
| 1390 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | |
| 1391 } | 1280 } |
| 1392 | 1281 |
| 1393 DCHECK(state() != GENERIC); | 1282 DCHECK(state() != GENERIC); |
| 1394 | 1283 |
| 1395 // Determine the list of receiver maps that this call site has seen, | 1284 // Determine the list of receiver maps that this call site has seen, |
| 1396 // adding the map that was just encountered. | 1285 // adding the map that was just encountered. |
| 1397 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1286 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
| 1398 // If the miss wasn't due to an unseen map, a polymorphic stub | 1287 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1399 // won't help, use the generic stub. | 1288 // won't help, use the generic stub. |
| 1400 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1289 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
| 1401 return megamorphic_stub(); | 1290 return megamorphic_stub(); |
| 1402 } | 1291 } |
| 1403 | 1292 |
| 1404 // If the maximum number of receiver maps has been exceeded, use the generic | 1293 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1405 // version of the IC. | 1294 // version of the IC. |
| 1406 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1295 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1407 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1296 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1408 return megamorphic_stub(); | 1297 return megamorphic_stub(); |
| 1409 } | 1298 } |
| 1410 | 1299 |
| 1411 if (FLAG_vector_ics) { | 1300 CodeHandleList handlers(target_receiver_maps.length()); |
| 1412 CodeHandleList handlers(target_receiver_maps.length()); | 1301 ElementHandlerCompiler compiler(isolate()); |
| 1413 ElementHandlerCompiler compiler(isolate()); | 1302 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
| 1414 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1303 ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers); |
| 1415 ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, | 1304 return null_handle; |
| 1416 &handlers); | |
| 1417 return null_handle; | |
| 1418 } | |
| 1419 | |
| 1420 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | |
| 1421 } | 1305 } |
| 1422 | 1306 |
| 1423 | 1307 |
| 1424 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1308 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
| 1425 Handle<Object> key) { | 1309 Handle<Object> key) { |
| 1426 if (MigrateDeprecated(object)) { | 1310 if (MigrateDeprecated(object)) { |
| 1427 Handle<Object> result; | 1311 Handle<Object> result; |
| 1428 ASSIGN_RETURN_ON_EXCEPTION( | 1312 ASSIGN_RETURN_ON_EXCEPTION( |
| 1429 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), | 1313 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
| 1430 Object); | 1314 Object); |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2363 | 2247 |
| 2364 | 2248 |
| 2365 // Used from ic-<arch>.cc. | 2249 // Used from ic-<arch>.cc. |
| 2366 RUNTIME_FUNCTION(LoadIC_Miss) { | 2250 RUNTIME_FUNCTION(LoadIC_Miss) { |
| 2367 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2251 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2368 HandleScope scope(isolate); | 2252 HandleScope scope(isolate); |
| 2369 Handle<Object> receiver = args.at<Object>(0); | 2253 Handle<Object> receiver = args.at<Object>(0); |
| 2370 Handle<Name> key = args.at<Name>(1); | 2254 Handle<Name> key = args.at<Name>(1); |
| 2371 Handle<Object> result; | 2255 Handle<Object> result; |
| 2372 | 2256 |
| 2373 if (FLAG_vector_ics) { | 2257 DCHECK(args.length() == 4); |
| 2374 DCHECK(args.length() == 4); | 2258 Handle<Smi> slot = args.at<Smi>(2); |
| 2375 Handle<Smi> slot = args.at<Smi>(2); | 2259 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2376 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 2260 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2377 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2261 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the |
| 2378 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the | 2262 // LoadIC miss handler if the handler misses. Since the vector Nexus is |
| 2379 // LoadIC miss handler if the handler misses. Since the vector Nexus is | 2263 // set up outside the IC, handle that here. |
| 2380 // set up outside the IC, handle that here. | 2264 if (vector->GetKind(vector_slot) == Code::LOAD_IC) { |
| 2381 if (vector->GetKind(vector_slot) == Code::LOAD_IC) { | 2265 LoadICNexus nexus(vector, vector_slot); |
| 2382 LoadICNexus nexus(vector, vector_slot); | 2266 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2383 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2267 ic.UpdateState(receiver, key); |
| 2384 ic.UpdateState(receiver, key); | 2268 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2385 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2386 ic.Load(receiver, key)); | |
| 2387 } else { | |
| 2388 DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); | |
| 2389 KeyedLoadICNexus nexus(vector, vector_slot); | |
| 2390 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | |
| 2391 ic.UpdateState(receiver, key); | |
| 2392 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2393 ic.Load(receiver, key)); | |
| 2394 } | |
| 2395 } else { | 2269 } else { |
| 2396 DCHECK(args.length() == 2); | 2270 DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); |
| 2397 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2271 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2272 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2398 ic.UpdateState(receiver, key); | 2273 ic.UpdateState(receiver, key); |
| 2399 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2274 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2400 } | 2275 } |
| 2401 return *result; | 2276 return *result; |
| 2402 } | 2277 } |
| 2403 | 2278 |
| 2404 | 2279 |
| 2405 // Used from ic-<arch>.cc | 2280 // Used from ic-<arch>.cc |
| 2406 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 2281 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { |
| 2407 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2282 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2408 HandleScope scope(isolate); | 2283 HandleScope scope(isolate); |
| 2409 Handle<Object> receiver = args.at<Object>(0); | 2284 Handle<Object> receiver = args.at<Object>(0); |
| 2410 Handle<Object> key = args.at<Object>(1); | 2285 Handle<Object> key = args.at<Object>(1); |
| 2411 Handle<Object> result; | 2286 Handle<Object> result; |
| 2412 | 2287 |
| 2413 if (FLAG_vector_ics) { | 2288 DCHECK(args.length() == 4); |
| 2414 DCHECK(args.length() == 4); | 2289 Handle<Smi> slot = args.at<Smi>(2); |
| 2415 Handle<Smi> slot = args.at<Smi>(2); | 2290 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2416 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 2291 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2417 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2292 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2418 KeyedLoadICNexus nexus(vector, vector_slot); | 2293 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2419 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2294 ic.UpdateState(receiver, key); |
| 2420 ic.UpdateState(receiver, key); | 2295 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2421 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2422 } else { | |
| 2423 DCHECK(args.length() == 2); | |
| 2424 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2425 ic.UpdateState(receiver, key); | |
| 2426 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2427 } | |
| 2428 | |
| 2429 return *result; | 2296 return *result; |
| 2430 } | 2297 } |
| 2431 | 2298 |
| 2432 | 2299 |
| 2433 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { | 2300 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { |
| 2434 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2301 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2435 HandleScope scope(isolate); | 2302 HandleScope scope(isolate); |
| 2436 Handle<Object> receiver = args.at<Object>(0); | 2303 Handle<Object> receiver = args.at<Object>(0); |
| 2437 Handle<Object> key = args.at<Object>(1); | 2304 Handle<Object> key = args.at<Object>(1); |
| 2438 Handle<Object> result; | 2305 Handle<Object> result; |
| 2439 | 2306 |
| 2440 if (FLAG_vector_ics) { | 2307 DCHECK(args.length() == 4); |
| 2441 DCHECK(args.length() == 4); | 2308 Handle<Smi> slot = args.at<Smi>(2); |
| 2442 Handle<Smi> slot = args.at<Smi>(2); | 2309 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 2443 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 2310 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2444 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2311 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2445 KeyedLoadICNexus nexus(vector, vector_slot); | 2312 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2446 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2313 ic.UpdateState(receiver, key); |
| 2447 ic.UpdateState(receiver, key); | 2314 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2448 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2449 } else { | |
| 2450 DCHECK(args.length() == 2); | |
| 2451 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2452 ic.UpdateState(receiver, key); | |
| 2453 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | |
| 2454 } | |
| 2455 | 2315 |
| 2456 return *result; | 2316 return *result; |
| 2457 } | 2317 } |
| 2458 | 2318 |
| 2459 | 2319 |
| 2460 // Used from ic-<arch>.cc. | 2320 // Used from ic-<arch>.cc. |
| 2461 RUNTIME_FUNCTION(StoreIC_Miss) { | 2321 RUNTIME_FUNCTION(StoreIC_Miss) { |
| 2462 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2322 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2463 HandleScope scope(isolate); | 2323 HandleScope scope(isolate); |
| 2464 DCHECK(args.length() == 3); | 2324 DCHECK(args.length() == 3); |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3009 } | 2869 } |
| 3010 | 2870 |
| 3011 | 2871 |
| 3012 RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { | 2872 RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) { |
| 3013 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2873 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 3014 HandleScope scope(isolate); | 2874 HandleScope scope(isolate); |
| 3015 Handle<Object> receiver = args.at<Object>(0); | 2875 Handle<Object> receiver = args.at<Object>(0); |
| 3016 Handle<Name> key = args.at<Name>(1); | 2876 Handle<Name> key = args.at<Name>(1); |
| 3017 Handle<Object> result; | 2877 Handle<Object> result; |
| 3018 | 2878 |
| 3019 if (FLAG_vector_ics) { | 2879 DCHECK(args.length() == 4); |
| 3020 DCHECK(args.length() == 4); | 2880 Handle<Smi> slot = args.at<Smi>(2); |
| 3021 Handle<Smi> slot = args.at<Smi>(2); | 2881 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); |
| 3022 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); | 2882 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 3023 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2883 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the |
| 3024 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the | 2884 // LoadIC miss handler if the handler misses. Since the vector Nexus is |
| 3025 // LoadIC miss handler if the handler misses. Since the vector Nexus is | 2885 // set up outside the IC, handle that here. |
| 3026 // set up outside the IC, handle that here. | 2886 if (vector->GetKind(vector_slot) == Code::LOAD_IC) { |
| 3027 if (vector->GetKind(vector_slot) == Code::LOAD_IC) { | 2887 LoadICNexus nexus(vector, vector_slot); |
| 3028 LoadICNexus nexus(vector, vector_slot); | 2888 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 3029 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2889 ic.UpdateState(receiver, key); |
| 3030 ic.UpdateState(receiver, key); | 2890 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 3031 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 3032 ic.Load(receiver, key)); | |
| 3033 } else { | |
| 3034 DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); | |
| 3035 KeyedLoadICNexus nexus(vector, vector_slot); | |
| 3036 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | |
| 3037 ic.UpdateState(receiver, key); | |
| 3038 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 3039 ic.Load(receiver, key)); | |
| 3040 } | |
| 3041 } else { | 2891 } else { |
| 3042 DCHECK(args.length() == 2); | 2892 DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC); |
| 3043 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2893 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2894 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 3044 ic.UpdateState(receiver, key); | 2895 ic.UpdateState(receiver, key); |
| 3045 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2896 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 3046 } | 2897 } |
| 3047 | 2898 |
| 3048 return *result; | 2899 return *result; |
| 3049 } | 2900 } |
| 3050 | 2901 |
| 3051 | 2902 |
| 3052 static const Address IC_utilities[] = { | 2903 static const Address IC_utilities[] = { |
| 3053 #define ADDR(name) FUNCTION_ADDR(name), | 2904 #define ADDR(name) FUNCTION_ADDR(name), |
| 3054 IC_UTIL_LIST(ADDR) NULL | 2905 IC_UTIL_LIST(ADDR) NULL |
| 3055 #undef ADDR | 2906 #undef ADDR |
| 3056 }; | 2907 }; |
| 3057 | 2908 |
| 3058 | 2909 |
| 3059 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2910 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 3060 } | 2911 } |
| 3061 } // namespace v8::internal | 2912 } // namespace v8::internal |
| OLD | NEW |