| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 | 494 |
| 495 // Try to find a suitable function delegate for the object at hand. | 495 // Try to find a suitable function delegate for the object at hand. |
| 496 result = TryCallAsFunction(result); | 496 result = TryCallAsFunction(result); |
| 497 if (result->IsJSFunction()) return result; | 497 if (result->IsJSFunction()) return result; |
| 498 | 498 |
| 499 // Otherwise, it will fail in the lookup step. | 499 // Otherwise, it will fail in the lookup step. |
| 500 } | 500 } |
| 501 | 501 |
| 502 // Lookup the property in the object. | 502 // Lookup the property in the object. |
| 503 LookupResult lookup; | 503 LookupResult lookup; |
| 504 { | 504 LookupForRead(*object, *name, &lookup); |
| 505 AssertNoGC nogc; // GC could invalidate the pointers held in lookup. | |
| 506 | 505 |
| 507 LookupForRead(*object, *name, &lookup); | 506 if (!lookup.IsProperty()) { |
| 507 // If the object does not have the requested property, check which |
| 508 // exception we need to throw. |
| 509 if (IsContextual(object)) { |
| 510 return ReferenceError("not_defined", name); |
| 511 } |
| 512 return TypeError("undefined_method", object, name); |
| 513 } |
| 508 | 514 |
| 509 if (!lookup.IsProperty()) { | 515 // Lookup is valid: Update inline cache and stub cache. |
| 510 // If the object does not have the requested property, check which | 516 if (FLAG_use_ic) { |
| 511 // exception we need to throw. | 517 UpdateCaches(&lookup, state, object, name); |
| 512 if (IsContextual(object)) { | |
| 513 return ReferenceError("not_defined", name); | |
| 514 } | |
| 515 return TypeError("undefined_method", object, name); | |
| 516 } | |
| 517 | |
| 518 // Lookup is valid: Update inline cache and stub cache. | |
| 519 if (FLAG_use_ic) { | |
| 520 UpdateCaches(&lookup, state, object, name); | |
| 521 } | |
| 522 } | 518 } |
| 523 | 519 |
| 524 // Get the property. | 520 // Get the property. |
| 525 PropertyAttributes attr; | 521 PropertyAttributes attr; |
| 526 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 522 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 527 if (result->IsFailure()) return result; | 523 if (result->IsFailure()) return result; |
| 528 if (lookup.type() == INTERCEPTOR) { | 524 if (lookup.type() == INTERCEPTOR) { |
| 529 // If the object does not have the requested property, check which | 525 // If the object does not have the requested property, check which |
| 530 // exception we need to throw. | 526 // exception we need to throw. |
| 531 if (attr == ABSENT) { | 527 if (attr == ABSENT) { |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 } | 780 } |
| 785 } | 781 } |
| 786 | 782 |
| 787 // Check if the name is trivially convertible to an index and get | 783 // Check if the name is trivially convertible to an index and get |
| 788 // the element if so. | 784 // the element if so. |
| 789 uint32_t index; | 785 uint32_t index; |
| 790 if (name->AsArrayIndex(&index)) return object->GetElement(index); | 786 if (name->AsArrayIndex(&index)) return object->GetElement(index); |
| 791 | 787 |
| 792 // Named lookup in the object. | 788 // Named lookup in the object. |
| 793 LookupResult lookup; | 789 LookupResult lookup; |
| 794 { | 790 LookupForRead(*object, *name, &lookup); |
| 795 AssertNoGC nogc; // GC could invalidate the pointers held in lookup. | |
| 796 | 791 |
| 797 LookupForRead(*object, *name, &lookup); | 792 // If we did not find a property, check if we need to throw an exception. |
| 793 if (!lookup.IsProperty()) { |
| 794 if (FLAG_strict || IsContextual(object)) { |
| 795 return ReferenceError("not_defined", name); |
| 796 } |
| 797 LOG(SuspectReadEvent(*name, *object)); |
| 798 } |
| 798 | 799 |
| 799 // If we did not find a property, check if we need to throw an exception. | 800 bool can_be_inlined = |
| 800 if (!lookup.IsProperty()) { | 801 FLAG_use_ic && |
| 801 if (FLAG_strict || IsContextual(object)) { | 802 state == PREMONOMORPHIC && |
| 802 return ReferenceError("not_defined", name); | 803 lookup.IsProperty() && |
| 803 } | 804 lookup.IsCacheable() && |
| 804 LOG(SuspectReadEvent(*name, *object)); | 805 lookup.holder() == *object && |
| 805 } | 806 lookup.type() == FIELD && |
| 807 !object->IsAccessCheckNeeded(); |
| 806 | 808 |
| 807 bool can_be_inlined = | 809 if (can_be_inlined) { |
| 808 FLAG_use_ic && | 810 Map* map = lookup.holder()->map(); |
| 809 state == PREMONOMORPHIC && | 811 // Property's index in the properties array. If negative we have |
| 810 lookup.IsProperty() && | 812 // an inobject property. |
| 811 lookup.IsCacheable() && | 813 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 812 lookup.holder() == *object && | 814 if (index < 0) { |
| 813 lookup.type() == FIELD && | 815 // Index is an offset from the end of the object. |
| 814 !object->IsAccessCheckNeeded(); | 816 int offset = map->instance_size() + (index * kPointerSize); |
| 815 | 817 if (PatchInlinedLoad(address(), map, offset)) { |
| 816 if (can_be_inlined) { | 818 set_target(megamorphic_stub()); |
| 817 Map* map = lookup.holder()->map(); | 819 #ifdef DEBUG |
| 818 // Property's index in the properties array. If negative we have | 820 if (FLAG_trace_ic) { |
| 819 // an inobject property. | 821 PrintF("[LoadIC : inline patch %s]\n", *name->ToCString()); |
| 820 int index = lookup.GetFieldIndex() - map->inobject_properties(); | |
| 821 if (index < 0) { | |
| 822 // Index is an offset from the end of the object. | |
| 823 int offset = map->instance_size() + (index * kPointerSize); | |
| 824 if (PatchInlinedLoad(address(), map, offset)) { | |
| 825 set_target(megamorphic_stub()); | |
| 826 #ifdef DEBUG | |
| 827 if (FLAG_trace_ic) { | |
| 828 PrintF("[LoadIC : inline patch %s]\n", *name->ToCString()); | |
| 829 } | |
| 830 #endif | |
| 831 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | |
| 832 #ifdef DEBUG | |
| 833 } else { | |
| 834 if (FLAG_trace_ic) { | |
| 835 PrintF("[LoadIC : no inline patch %s (patching failed)]\n", | |
| 836 *name->ToCString()); | |
| 837 } | |
| 838 } | 822 } |
| 823 #endif |
| 824 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
| 825 #ifdef DEBUG |
| 839 } else { | 826 } else { |
| 840 if (FLAG_trace_ic) { | 827 if (FLAG_trace_ic) { |
| 841 PrintF("[LoadIC : no inline patch %s (not inobject)]\n", | 828 PrintF("[LoadIC : no inline patch %s (patching failed)]\n", |
| 842 *name->ToCString()); | 829 *name->ToCString()); |
| 843 } | 830 } |
| 844 } | 831 } |
| 845 } else { | 832 } else { |
| 846 if (FLAG_use_ic && state == PREMONOMORPHIC) { | 833 if (FLAG_trace_ic) { |
| 847 if (FLAG_trace_ic) { | 834 PrintF("[LoadIC : no inline patch %s (not inobject)]\n", |
| 848 PrintF("[LoadIC : no inline patch %s (not inlinable)]\n", | 835 *name->ToCString()); |
| 849 *name->ToCString()); | |
| 850 #endif | |
| 851 } | |
| 852 } | 836 } |
| 853 } | 837 } |
| 838 } else { |
| 839 if (FLAG_use_ic && state == PREMONOMORPHIC) { |
| 840 if (FLAG_trace_ic) { |
| 841 PrintF("[LoadIC : no inline patch %s (not inlinable)]\n", |
| 842 *name->ToCString()); |
| 843 #endif |
| 844 } |
| 845 } |
| 846 } |
| 854 | 847 |
| 855 // Update inline cache and stub cache. | 848 // Update inline cache and stub cache. |
| 856 if (FLAG_use_ic) { | 849 if (FLAG_use_ic) { |
| 857 UpdateCaches(&lookup, state, object, name); | 850 UpdateCaches(&lookup, state, object, name); |
| 858 } | |
| 859 } | 851 } |
| 860 | 852 |
| 861 PropertyAttributes attr; | 853 PropertyAttributes attr; |
| 862 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 854 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
| 863 // Get the property. | 855 // Get the property. |
| 864 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 856 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 865 if (result->IsFailure()) return result; | 857 if (result->IsFailure()) return result; |
| 866 // If the property is not present, check if we need to throw an | 858 // If the property is not present, check if we need to throw an |
| 867 // exception. | 859 // exception. |
| 868 if (attr == ABSENT && IsContextual(object)) { | 860 if (attr == ABSENT && IsContextual(object)) { |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 uint32_t index = 0; | 1030 uint32_t index = 0; |
| 1039 if (name->AsArrayIndex(&index)) { | 1031 if (name->AsArrayIndex(&index)) { |
| 1040 HandleScope scope; | 1032 HandleScope scope; |
| 1041 // Rewrite to the generic keyed load stub. | 1033 // Rewrite to the generic keyed load stub. |
| 1042 if (FLAG_use_ic) set_target(generic_stub()); | 1034 if (FLAG_use_ic) set_target(generic_stub()); |
| 1043 return Runtime::GetElementOrCharAt(object, index); | 1035 return Runtime::GetElementOrCharAt(object, index); |
| 1044 } | 1036 } |
| 1045 | 1037 |
| 1046 // Named lookup. | 1038 // Named lookup. |
| 1047 LookupResult lookup; | 1039 LookupResult lookup; |
| 1048 { | 1040 LookupForRead(*object, *name, &lookup); |
| 1049 AssertNoGC nogc; // GC could invalidate the pointers held in lookup. | |
| 1050 | 1041 |
| 1051 LookupForRead(*object, *name, &lookup); | 1042 // If we did not find a property, check if we need to throw an exception. |
| 1052 | 1043 if (!lookup.IsProperty()) { |
| 1053 // If we did not find a property, check if we need to throw an exception. | 1044 if (FLAG_strict || IsContextual(object)) { |
| 1054 if (!lookup.IsProperty()) { | 1045 return ReferenceError("not_defined", name); |
| 1055 if (FLAG_strict || IsContextual(object)) { | |
| 1056 return ReferenceError("not_defined", name); | |
| 1057 } | |
| 1058 } | |
| 1059 | |
| 1060 if (FLAG_use_ic) { | |
| 1061 UpdateCaches(&lookup, state, object, name); | |
| 1062 } | 1046 } |
| 1063 } | 1047 } |
| 1064 | 1048 |
| 1049 if (FLAG_use_ic) { |
| 1050 UpdateCaches(&lookup, state, object, name); |
| 1051 } |
| 1052 |
| 1065 PropertyAttributes attr; | 1053 PropertyAttributes attr; |
| 1066 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 1054 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
| 1067 // Get the property. | 1055 // Get the property. |
| 1068 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 1056 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 1069 if (result->IsFailure()) return result; | 1057 if (result->IsFailure()) return result; |
| 1070 // If the property is not present, check if we need to throw an | 1058 // If the property is not present, check if we need to throw an |
| 1071 // exception. | 1059 // exception. |
| 1072 if (attr == ABSENT && IsContextual(object)) { | 1060 if (attr == ABSENT && IsContextual(object)) { |
| 1073 return ReferenceError("not_defined", name); | 1061 return ReferenceError("not_defined", name); |
| 1074 } | 1062 } |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 #ifdef DEBUG | 1238 #ifdef DEBUG |
| 1251 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 1239 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
| 1252 #endif | 1240 #endif |
| 1253 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); | 1241 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); |
| 1254 set_target(target); | 1242 set_target(target); |
| 1255 return receiver->SetProperty(*name, *value, NONE); | 1243 return receiver->SetProperty(*name, *value, NONE); |
| 1256 } | 1244 } |
| 1257 | 1245 |
| 1258 // Lookup the property locally in the receiver. | 1246 // Lookup the property locally in the receiver. |
| 1259 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1247 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
| 1260 AssertNoGC nogc; // GC could invalidate the pointers held in lookup. | |
| 1261 | |
| 1262 LookupResult lookup; | 1248 LookupResult lookup; |
| 1263 | 1249 |
| 1264 if (LookupForWrite(*receiver, *name, &lookup)) { | 1250 if (LookupForWrite(*receiver, *name, &lookup)) { |
| 1265 bool can_be_inlined = | 1251 bool can_be_inlined = |
| 1266 state == UNINITIALIZED && | 1252 state == UNINITIALIZED && |
| 1267 lookup.IsProperty() && | 1253 lookup.IsProperty() && |
| 1268 lookup.holder() == *receiver && | 1254 lookup.holder() == *receiver && |
| 1269 lookup.type() == FIELD && | 1255 lookup.type() == FIELD && |
| 1270 !receiver->IsAccessCheckNeeded(); | 1256 !receiver->IsAccessCheckNeeded(); |
| 1271 | 1257 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 | 1411 |
| 1426 // Check if the given name is an array index. | 1412 // Check if the given name is an array index. |
| 1427 uint32_t index; | 1413 uint32_t index; |
| 1428 if (name->AsArrayIndex(&index)) { | 1414 if (name->AsArrayIndex(&index)) { |
| 1429 HandleScope scope; | 1415 HandleScope scope; |
| 1430 Handle<Object> result = SetElement(receiver, index, value); | 1416 Handle<Object> result = SetElement(receiver, index, value); |
| 1431 if (result.is_null()) return Failure::Exception(); | 1417 if (result.is_null()) return Failure::Exception(); |
| 1432 return *value; | 1418 return *value; |
| 1433 } | 1419 } |
| 1434 | 1420 |
| 1435 { | 1421 // Lookup the property locally in the receiver. |
| 1436 AssertNoGC nogc; // GC could invalidate the pointers held in lookup. | 1422 LookupResult lookup; |
| 1423 receiver->LocalLookup(*name, &lookup); |
| 1437 | 1424 |
| 1438 // Lookup the property locally in the receiver. | 1425 // Update inline cache and stub cache. |
| 1439 LookupResult lookup; | 1426 if (FLAG_use_ic) { |
| 1440 receiver->LocalLookup(*name, &lookup); | 1427 UpdateCaches(&lookup, state, receiver, name, value); |
| 1441 | |
| 1442 // Update inline cache and stub cache. | |
| 1443 if (FLAG_use_ic) { | |
| 1444 UpdateCaches(&lookup, state, receiver, name, value); | |
| 1445 } | |
| 1446 } | 1428 } |
| 1447 | 1429 |
| 1448 // Set the property. | 1430 // Set the property. |
| 1449 return receiver->SetProperty(*name, *value, NONE); | 1431 return receiver->SetProperty(*name, *value, NONE); |
| 1450 } | 1432 } |
| 1451 | 1433 |
| 1452 // Do not use ICs for objects that require access checks (including | 1434 // Do not use ICs for objects that require access checks (including |
| 1453 // the global object). | 1435 // the global object). |
| 1454 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1436 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 1455 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1437 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1836 #undef ADDR | 1818 #undef ADDR |
| 1837 }; | 1819 }; |
| 1838 | 1820 |
| 1839 | 1821 |
| 1840 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1822 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 1841 return IC_utilities[id]; | 1823 return IC_utilities[id]; |
| 1842 } | 1824 } |
| 1843 | 1825 |
| 1844 | 1826 |
| 1845 } } // namespace v8::internal | 1827 } } // namespace v8::internal |
| OLD | NEW |