| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 } | 135 } |
| 136 | 136 |
| 137 | 137 |
| 138 #define TRACE_IC(type, name) TraceIC(type, name) | 138 #define TRACE_IC(type, name) TraceIC(type, name) |
| 139 | 139 |
| 140 | 140 |
| 141 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, | 141 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, |
| 142 bool for_queries_only) | 142 bool for_queries_only) |
| 143 : isolate_(isolate), | 143 : isolate_(isolate), |
| 144 target_set_(false), | 144 target_set_(false), |
| 145 vector_set_(false), |
| 145 target_maps_set_(false), | 146 target_maps_set_(false), |
| 146 nexus_(nexus) { | 147 nexus_(nexus) { |
| 147 // To improve the performance of the (much used) IC code, we unfold a few | 148 // To improve the performance of the (much used) IC code, we unfold a few |
| 148 // levels of the stack frame iteration code. This yields a ~35% speedup when | 149 // levels of the stack frame iteration code. This yields a ~35% speedup when |
| 149 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 150 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 150 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); | 151 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); |
| 151 Address constant_pool = NULL; | 152 Address constant_pool = NULL; |
| 152 if (FLAG_enable_ool_constant_pool) { | 153 if (FLAG_enable_ool_constant_pool) { |
| 153 constant_pool = | 154 constant_pool = |
| 154 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); | 155 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 nexus->ConfigureGeneric(); | 630 nexus->ConfigureGeneric(); |
| 630 } else if (new_state == PREMONOMORPHIC) { | 631 } else if (new_state == PREMONOMORPHIC) { |
| 631 nexus->ConfigurePremonomorphic(); | 632 nexus->ConfigurePremonomorphic(); |
| 632 } else { | 633 } else { |
| 633 UNREACHABLE(); | 634 UNREACHABLE(); |
| 634 } | 635 } |
| 635 } else { | 636 } else { |
| 636 UNREACHABLE(); | 637 UNREACHABLE(); |
| 637 } | 638 } |
| 638 | 639 |
| 640 vector_set_ = true; |
| 639 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 641 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 640 new_state); | 642 new_state); |
| 641 } | 643 } |
| 642 | 644 |
| 643 | 645 |
| 644 void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, | 646 void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, |
| 645 Handle<Code> handler) { | 647 Handle<Code> handler) { |
| 646 DCHECK(UseVector()); | 648 DCHECK(UseVector()); |
| 647 if (kind() == Code::LOAD_IC) { | 649 if (kind() == Code::LOAD_IC) { |
| 648 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 650 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 649 nexus->ConfigureMonomorphic(type, handler); | 651 nexus->ConfigureMonomorphic(type, handler); |
| 650 } else { | 652 } else { |
| 651 DCHECK(kind() == Code::KEYED_LOAD_IC); | 653 DCHECK(kind() == Code::KEYED_LOAD_IC); |
| 652 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 654 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 653 nexus->ConfigureMonomorphic(name, type, handler); | 655 nexus->ConfigureMonomorphic(name, type, handler); |
| 654 } | 656 } |
| 655 | 657 |
| 658 vector_set_ = true; |
| 656 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 659 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 657 MONOMORPHIC); | 660 MONOMORPHIC); |
| 658 } | 661 } |
| 659 | 662 |
| 660 | 663 |
| 661 void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types, | 664 void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types, |
| 662 CodeHandleList* handlers) { | 665 CodeHandleList* handlers) { |
| 663 DCHECK(UseVector()); | 666 DCHECK(UseVector()); |
| 664 if (kind() == Code::LOAD_IC) { | 667 if (kind() == Code::LOAD_IC) { |
| 665 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 668 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 666 nexus->ConfigurePolymorphic(types, handlers); | 669 nexus->ConfigurePolymorphic(types, handlers); |
| 667 } else { | 670 } else { |
| 668 DCHECK(kind() == Code::KEYED_LOAD_IC); | 671 DCHECK(kind() == Code::KEYED_LOAD_IC); |
| 669 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 672 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 670 nexus->ConfigurePolymorphic(name, types, handlers); | 673 nexus->ConfigurePolymorphic(name, types, handlers); |
| 671 } | 674 } |
| 672 | 675 |
| 676 vector_set_ = true; |
| 673 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), | 677 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(), |
| 674 POLYMORPHIC); | 678 POLYMORPHIC); |
| 675 } | 679 } |
| 676 | 680 |
| 677 | 681 |
| 678 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { | 682 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { |
| 679 // If the object is undefined or null it's illegal to try to get any | 683 // If the object is undefined or null it's illegal to try to get any |
| 680 // of its properties; throw a TypeError in that case. | 684 // of its properties; throw a TypeError in that case. |
| 681 if (object->IsUndefined() || object->IsNull()) { | 685 if (object->IsUndefined() || object->IsNull()) { |
| 682 return TypeError("non_object_property_load", object, name); | 686 return TypeError("non_object_property_load", object, name); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 if (UseVector()) { | 942 if (UseVector()) { |
| 939 ConfigureVectorState(kind() == Code::KEYED_LOAD_IC ? GENERIC | 943 ConfigureVectorState(kind() == Code::KEYED_LOAD_IC ? GENERIC |
| 940 : MEGAMORPHIC); | 944 : MEGAMORPHIC); |
| 941 } else { | 945 } else { |
| 942 set_target(*megamorphic_stub()); | 946 set_target(*megamorphic_stub()); |
| 943 } | 947 } |
| 944 // Fall through. | 948 // Fall through. |
| 945 case MEGAMORPHIC: | 949 case MEGAMORPHIC: |
| 946 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 950 UpdateMegamorphicCache(*receiver_type(), *name, *code); |
| 947 // Indicate that we've handled this case. | 951 // Indicate that we've handled this case. |
| 948 target_set_ = true; | 952 if (UseVector()) { |
| 953 vector_set_ = true; |
| 954 } else { |
| 955 target_set_ = true; |
| 956 } |
| 949 break; | 957 break; |
| 950 case DEBUG_STUB: | 958 case DEBUG_STUB: |
| 951 break; | 959 break; |
| 952 case DEFAULT: | 960 case DEFAULT: |
| 953 UNREACHABLE(); | 961 UNREACHABLE(); |
| 954 break; | 962 break; |
| 955 case GENERIC: | 963 case GENERIC: |
| 956 // The generic keyed store stub re-uses store handlers, which can miss. | 964 // The generic keyed store stub re-uses store handlers, which can miss. |
| 957 // That's ok, no reason to do anything. | 965 // That's ok, no reason to do anything. |
| 958 DCHECK(target()->kind() == Code::KEYED_STORE_IC); | 966 DCHECK(target()->kind() == Code::KEYED_STORE_IC); |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 } | 1350 } |
| 1343 | 1351 |
| 1344 DCHECK(state() != GENERIC); | 1352 DCHECK(state() != GENERIC); |
| 1345 | 1353 |
| 1346 // Determine the list of receiver maps that this call site has seen, | 1354 // Determine the list of receiver maps that this call site has seen, |
| 1347 // adding the map that was just encountered. | 1355 // adding the map that was just encountered. |
| 1348 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1356 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
| 1349 // If the miss wasn't due to an unseen map, a polymorphic stub | 1357 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1350 // won't help, use the generic stub. | 1358 // won't help, use the generic stub. |
| 1351 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1359 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
| 1352 if (FLAG_vector_ics) { | |
| 1353 ConfigureVectorState(GENERIC); | |
| 1354 return null_handle; | |
| 1355 } | |
| 1356 return generic_stub(); | 1360 return generic_stub(); |
| 1357 } | 1361 } |
| 1358 | 1362 |
| 1359 // If the maximum number of receiver maps has been exceeded, use the generic | 1363 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1360 // version of the IC. | 1364 // version of the IC. |
| 1361 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1365 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1362 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1366 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1363 if (FLAG_vector_ics) { | |
| 1364 ConfigureVectorState(GENERIC); | |
| 1365 return null_handle; | |
| 1366 } | |
| 1367 return generic_stub(); | 1367 return generic_stub(); |
| 1368 } | 1368 } |
| 1369 | 1369 |
| 1370 if (FLAG_vector_ics) { | 1370 if (FLAG_vector_ics) { |
| 1371 CodeHandleList handlers(target_receiver_maps.length()); | 1371 CodeHandleList handlers(target_receiver_maps.length()); |
| 1372 ElementHandlerCompiler compiler(isolate()); | 1372 ElementHandlerCompiler compiler(isolate()); |
| 1373 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1373 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
| 1374 TypeHandleList types(target_receiver_maps.length()); | 1374 TypeHandleList types(target_receiver_maps.length()); |
| 1375 for (int i = 0; i < target_receiver_maps.length(); i++) { | 1375 for (int i = 0; i < target_receiver_maps.length(); i++) { |
| 1376 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); | 1376 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1406 Object); | 1406 Object); |
| 1407 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1407 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1408 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1408 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
| 1409 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1409 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
| 1410 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { | 1410 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { |
| 1411 stub = LoadElementStub(receiver); | 1411 stub = LoadElementStub(receiver); |
| 1412 } | 1412 } |
| 1413 } | 1413 } |
| 1414 } | 1414 } |
| 1415 | 1415 |
| 1416 if (!is_target_set()) { | 1416 if (!UseVector()) { |
| 1417 if (!FLAG_vector_ics) { | 1417 if (!is_target_set()) { |
| 1418 Code* generic = *generic_stub(); | 1418 Code* generic = *generic_stub(); |
| 1419 if (*stub == generic) { | 1419 if (*stub == generic) { |
| 1420 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1420 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1421 } | 1421 } |
| 1422 | 1422 |
| 1423 set_target(*stub); | 1423 set_target(*stub); |
| 1424 TRACE_IC("LoadIC", key); |
| 1424 } | 1425 } |
| 1425 TRACE_IC("LoadIC", key); | 1426 } else { |
| 1427 if (!is_vector_set() || stub.is_null()) { |
| 1428 Code* generic = *generic_stub(); |
| 1429 if (!stub.is_null() && *stub == generic) { |
| 1430 ConfigureVectorState(GENERIC); |
| 1431 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1432 } |
| 1433 |
| 1434 TRACE_IC("LoadIC", key); |
| 1435 } |
| 1426 } | 1436 } |
| 1427 | 1437 |
| 1428 if (!load_handle.is_null()) return load_handle; | 1438 if (!load_handle.is_null()) return load_handle; |
| 1429 Handle<Object> result; | 1439 Handle<Object> result; |
| 1430 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 1440 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| 1431 Runtime::GetObjectProperty(isolate(), object, key), | 1441 Runtime::GetObjectProperty(isolate(), object, key), |
| 1432 Object); | 1442 Object); |
| 1433 return result; | 1443 return result; |
| 1434 } | 1444 } |
| 1435 | 1445 |
| (...skipping 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2967 static const Address IC_utilities[] = { | 2977 static const Address IC_utilities[] = { |
| 2968 #define ADDR(name) FUNCTION_ADDR(name), | 2978 #define ADDR(name) FUNCTION_ADDR(name), |
| 2969 IC_UTIL_LIST(ADDR) NULL | 2979 IC_UTIL_LIST(ADDR) NULL |
| 2970 #undef ADDR | 2980 #undef ADDR |
| 2971 }; | 2981 }; |
| 2972 | 2982 |
| 2973 | 2983 |
| 2974 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2984 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 2975 } | 2985 } |
| 2976 } // namespace v8::internal | 2986 } // namespace v8::internal |
| OLD | NEW |