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