OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
856 stub = string_length_stub.GetCode(isolate()); | 856 stub = string_length_stub.GetCode(isolate()); |
857 } else if (state() != MEGAMORPHIC) { | 857 } else if (state() != MEGAMORPHIC) { |
858 ASSERT(state() != GENERIC); | 858 ASSERT(state() != GENERIC); |
859 stub = megamorphic_stub(); | 859 stub = megamorphic_stub(); |
860 } | 860 } |
861 if (!stub.is_null()) { | 861 if (!stub.is_null()) { |
862 set_target(*stub); | 862 set_target(*stub); |
863 #ifdef DEBUG | 863 #ifdef DEBUG |
864 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); | 864 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); |
865 #endif | 865 #endif |
866 } else if (kind() == Code::KEYED_LOAD_IC) { | |
867 set_target(*generic_stub()); | |
868 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "access check needed"); | |
danno
2013/10/22 14:52:24
change comment appropriately
| |
866 } | 869 } |
867 // Get the string if we have a string wrapper object. | 870 // Get the string if we have a string wrapper object. |
868 String* string = String::cast(JSValue::cast(*object)->value()); | 871 String* string = String::cast(JSValue::cast(*object)->value()); |
869 return Smi::FromInt(string->length()); | 872 return Smi::FromInt(string->length()); |
870 } | 873 } |
871 | 874 |
872 // Use specialized code for getting prototype of functions. | 875 // Use specialized code for getting prototype of functions. |
873 if (object->IsJSFunction() && | 876 if (object->IsJSFunction() && |
874 name->Equals(isolate()->heap()->prototype_string()) && | 877 name->Equals(isolate()->heap()->prototype_string()) && |
875 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 878 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
876 Handle<Code> stub; | 879 Handle<Code> stub; |
877 if (state() == UNINITIALIZED) { | 880 if (state() == UNINITIALIZED) { |
878 stub = pre_monomorphic_stub(); | 881 stub = pre_monomorphic_stub(); |
879 } else if (state() == PREMONOMORPHIC) { | 882 } else if (state() == PREMONOMORPHIC) { |
880 FunctionPrototypeStub function_prototype_stub(kind()); | 883 FunctionPrototypeStub function_prototype_stub(kind()); |
881 stub = function_prototype_stub.GetCode(isolate()); | 884 stub = function_prototype_stub.GetCode(isolate()); |
882 } else if (state() != MEGAMORPHIC) { | 885 } else if (state() != MEGAMORPHIC) { |
883 ASSERT(state() != GENERIC); | 886 ASSERT(state() != GENERIC); |
884 stub = megamorphic_stub(); | 887 stub = megamorphic_stub(); |
885 } | 888 } |
886 if (!stub.is_null()) { | 889 if (!stub.is_null()) { |
887 set_target(*stub); | 890 set_target(*stub); |
888 #ifdef DEBUG | 891 #ifdef DEBUG |
889 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 892 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
890 #endif | 893 #endif |
894 } else if (kind() == Code::KEYED_LOAD_IC) { | |
895 set_target(*generic_stub()); | |
896 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "access check needed"); | |
danno
2013/10/22 14:52:24
change comment appropriately
| |
891 } | 897 } |
892 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 898 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
893 } | 899 } |
894 } | 900 } |
895 | 901 |
896 // Check if the name is trivially convertible to an index and get | 902 // Check if the name is trivially convertible to an index and get |
897 // the element or char if so. | 903 // the element or char if so. |
898 uint32_t index; | 904 uint32_t index; |
899 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 905 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
900 // Rewrite to the generic keyed load stub. | 906 // Rewrite to the generic keyed load stub. |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1115 KeyedLoadFieldStub stub(inobject, offset, representation); | 1121 KeyedLoadFieldStub stub(inobject, offset, representation); |
1116 return stub.GetCode(isolate()); | 1122 return stub.GetCode(isolate()); |
1117 } | 1123 } |
1118 } | 1124 } |
1119 | 1125 |
1120 void LoadIC::UpdateCaches(LookupResult* lookup, | 1126 void LoadIC::UpdateCaches(LookupResult* lookup, |
1121 Handle<Object> object, | 1127 Handle<Object> object, |
1122 Handle<String> name) { | 1128 Handle<String> name) { |
1123 // TODO(verwaest): It would be nice to support loading fields from smis as | 1129 // TODO(verwaest): It would be nice to support loading fields from smis as |
1124 // well. For now just fail to update the cache. | 1130 // well. For now just fail to update the cache. |
1125 if (!object->IsHeapObject()) return; | 1131 if (!object->IsHeapObject()) { |
1132 if (kind() == Code::KEYED_LOAD_IC) { | |
1133 set_target(*generic_stub()); | |
1134 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "access check needed"); | |
danno
2013/10/22 14:52:24
comment should be: not heap object
| |
1135 } | |
1136 return; | |
1137 } | |
1126 | 1138 |
1127 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1139 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
1128 | 1140 |
1129 Handle<Code> code; | 1141 Handle<Code> code; |
1130 if (state() == UNINITIALIZED) { | 1142 if (state() == UNINITIALIZED) { |
1131 // This is the first time we execute this inline cache. | 1143 // This is the first time we execute this inline cache. |
1132 // Set the target to the pre monomorphic stub to delay | 1144 // Set the target to the pre monomorphic stub to delay |
1133 // setting the monomorphic state. | 1145 // setting the monomorphic state. |
1134 code = pre_monomorphic_stub(); | 1146 code = pre_monomorphic_stub(); |
1135 } else if (!lookup->IsCacheable()) { | 1147 } else if (!lookup->IsCacheable()) { |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1364 } | 1376 } |
1365 | 1377 |
1366 // Check for values that can be converted into an internalized string directly | 1378 // Check for values that can be converted into an internalized string directly |
1367 // or is representable as a smi. | 1379 // or is representable as a smi. |
1368 key = TryConvertKey(key, isolate()); | 1380 key = TryConvertKey(key, isolate()); |
1369 | 1381 |
1370 if (key->IsInternalizedString()) { | 1382 if (key->IsInternalizedString()) { |
1371 return LoadIC::Load(object, Handle<String>::cast(key)); | 1383 return LoadIC::Load(object, Handle<String>::cast(key)); |
1372 } | 1384 } |
1373 | 1385 |
1374 if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1386 if (FLAG_use_ic) { |
1375 ASSERT(!object->IsJSGlobalProxy()); | |
1376 Handle<Code> stub = generic_stub(); | 1387 Handle<Code> stub = generic_stub(); |
1377 if (miss_mode == MISS_FORCE_GENERIC) { | 1388 if (!object->IsAccessCheckNeeded()) { |
1378 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | 1389 ASSERT(!object->IsJSGlobalProxy()); |
1379 } else if (object->IsString() && key->IsNumber()) { | 1390 if (miss_mode == MISS_FORCE_GENERIC) { |
1380 if (state() == UNINITIALIZED) stub = string_stub(); | 1391 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
1381 } else if (object->IsJSObject()) { | 1392 } else if (object->IsString() && key->IsNumber()) { |
1382 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1393 if (state() == UNINITIALIZED) stub = string_stub(); |
1383 if (receiver->elements()->map() == | 1394 } else if (object->IsJSObject()) { |
1384 isolate()->heap()->non_strict_arguments_elements_map()) { | 1395 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1385 stub = non_strict_arguments_stub(); | 1396 if (receiver->elements()->map() == |
1386 } else if (receiver->HasIndexedInterceptor()) { | 1397 isolate()->heap()->non_strict_arguments_elements_map()) { |
1387 stub = indexed_interceptor_stub(); | 1398 stub = non_strict_arguments_stub(); |
1388 } else if (!key->ToSmi()->IsFailure() && | 1399 } else if (receiver->HasIndexedInterceptor()) { |
1389 (!target().is_identical_to(non_strict_arguments_stub()))) { | 1400 stub = indexed_interceptor_stub(); |
1390 stub = LoadElementStub(receiver); | 1401 } else if (!key->ToSmi()->IsFailure() && |
1402 (!target().is_identical_to(non_strict_arguments_stub()))) { | |
1403 stub = LoadElementStub(receiver); | |
1404 } else { | |
1405 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "access check needed"); | |
danno
2013/10/22 14:52:24
Should be: "not otherwise handled"
| |
1406 } | |
1407 } else { | |
1408 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "access check needed"); | |
danno
2013/10/22 14:52:24
should be: "not JSObject"
| |
1391 } | 1409 } |
1410 } else { | |
1411 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "access check needed"); | |
1392 } | 1412 } |
1393 | |
1394 ASSERT(!stub.is_null()); | 1413 ASSERT(!stub.is_null()); |
1395 set_target(*stub); | 1414 set_target(*stub); |
1396 TRACE_IC("LoadIC", key); | 1415 TRACE_IC("LoadIC", key); |
1397 } | 1416 } |
1398 | 1417 |
1399 | |
1400 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1418 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
1401 } | 1419 } |
1402 | 1420 |
1403 | 1421 |
1404 static bool LookupForWrite(Handle<JSObject> receiver, | 1422 static bool LookupForWrite(Handle<JSObject> receiver, |
1405 Handle<String> name, | 1423 Handle<String> name, |
1406 Handle<Object> value, | 1424 Handle<Object> value, |
1407 LookupResult* lookup, | 1425 LookupResult* lookup, |
1408 IC* ic) { | 1426 IC* ic) { |
1409 Handle<JSObject> holder = receiver; | 1427 Handle<JSObject> holder = receiver; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1555 } | 1573 } |
1556 if (FLAG_use_ic) { | 1574 if (FLAG_use_ic) { |
1557 if (state() == UNINITIALIZED) { | 1575 if (state() == UNINITIALIZED) { |
1558 Handle<Code> stub = pre_monomorphic_stub(); | 1576 Handle<Code> stub = pre_monomorphic_stub(); |
1559 set_target(*stub); | 1577 set_target(*stub); |
1560 TRACE_IC("StoreIC", name); | 1578 TRACE_IC("StoreIC", name); |
1561 } else if (can_store) { | 1579 } else if (can_store) { |
1562 UpdateCaches(&lookup, receiver, name, value); | 1580 UpdateCaches(&lookup, receiver, name, value); |
1563 } else if (!name->IsCacheable(isolate()) || | 1581 } else if (!name->IsCacheable(isolate()) || |
1564 lookup.IsNormal() || | 1582 lookup.IsNormal() || |
1565 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1583 (lookup.IsField() && lookup.CanHoldValue(value)) || |
1566 Handle<Code> stub = generic_stub(); | 1584 kind() == Code::KEYED_STORE_IC) { |
1567 set_target(*stub); | 1585 set_target(*generic_stub()); |
1586 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "access check needed"); | |
1587 TRACE_IC("StoreIC", name); | |
1568 } | 1588 } |
1569 } | 1589 } |
1570 | 1590 |
1571 // Set the property. | 1591 // Set the property. |
1572 Handle<Object> result = JSReceiver::SetProperty( | 1592 Handle<Object> result = JSReceiver::SetProperty( |
1573 receiver, name, value, NONE, strict_mode(), store_mode); | 1593 receiver, name, value, NONE, strict_mode(), store_mode); |
1574 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1594 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1575 return *result; | 1595 return *result; |
1576 } | 1596 } |
1577 | 1597 |
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2713 #undef ADDR | 2733 #undef ADDR |
2714 }; | 2734 }; |
2715 | 2735 |
2716 | 2736 |
2717 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2737 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2718 return IC_utilities[id]; | 2738 return IC_utilities[id]; |
2719 } | 2739 } |
2720 | 2740 |
2721 | 2741 |
2722 } } // namespace v8::internal | 2742 } } // namespace v8::internal |
OLD | NEW |