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