Chromium Code Reviews| 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 |