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 |