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 |