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