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 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 if (!lookup.IsProperty()) { | 429 if (!lookup.IsProperty()) { |
430 // If the object does not have the requested property, check which | 430 // If the object does not have the requested property, check which |
431 // exception we need to throw. | 431 // exception we need to throw. |
432 if (IsContextual(object)) { | 432 if (IsContextual(object)) { |
433 return ReferenceError("not_defined", name); | 433 return ReferenceError("not_defined", name); |
434 } | 434 } |
435 return TypeError("undefined_method", object, name); | 435 return TypeError("undefined_method", object, name); |
436 } | 436 } |
437 | 437 |
438 // Lookup is valid: Update inline cache and stub cache. | 438 // Lookup is valid: Update inline cache and stub cache. |
439 if (FLAG_use_ic && lookup.IsLoaded()) { | 439 if (FLAG_use_ic) { |
440 UpdateCaches(&lookup, state, object, name); | 440 UpdateCaches(&lookup, state, object, name); |
441 } | 441 } |
442 | 442 |
443 // Get the property. | 443 // Get the property. |
444 PropertyAttributes attr; | 444 PropertyAttributes attr; |
445 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 445 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
446 if (result->IsFailure()) return result; | 446 if (result->IsFailure()) return result; |
447 if (lookup.type() == INTERCEPTOR) { | 447 if (lookup.type() == INTERCEPTOR) { |
448 // If the object does not have the requested property, check which | 448 // If the object does not have the requested property, check which |
449 // exception we need to throw. | 449 // exception we need to throw. |
(...skipping 27 matching lines...) Expand all Loading... |
477 result = TryCallAsFunction(result); | 477 result = TryCallAsFunction(result); |
478 return result->IsJSFunction() ? | 478 return result->IsJSFunction() ? |
479 result : TypeError("property_not_function", object, name); | 479 result : TypeError("property_not_function", object, name); |
480 } | 480 } |
481 | 481 |
482 | 482 |
483 void CallIC::UpdateCaches(LookupResult* lookup, | 483 void CallIC::UpdateCaches(LookupResult* lookup, |
484 State state, | 484 State state, |
485 Handle<Object> object, | 485 Handle<Object> object, |
486 Handle<String> name) { | 486 Handle<String> name) { |
487 ASSERT(lookup->IsLoaded()); | |
488 // Bail out if we didn't find a result. | 487 // Bail out if we didn't find a result. |
489 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 488 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
490 | 489 |
491 // Compute the number of arguments. | 490 // Compute the number of arguments. |
492 int argc = target()->arguments_count(); | 491 int argc = target()->arguments_count(); |
493 InLoopFlag in_loop = target()->ic_in_loop(); | 492 InLoopFlag in_loop = target()->ic_in_loop(); |
494 Object* code = NULL; | 493 Object* code = NULL; |
495 | 494 |
496 if (state == UNINITIALIZED) { | 495 if (state == UNINITIALIZED) { |
497 // This is the first time we execute this inline cache. | 496 // This is the first time we execute this inline cache. |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 if (FLAG_strict || IsContextual(object)) { | 639 if (FLAG_strict || IsContextual(object)) { |
641 return ReferenceError("not_defined", name); | 640 return ReferenceError("not_defined", name); |
642 } | 641 } |
643 LOG(SuspectReadEvent(*name, *object)); | 642 LOG(SuspectReadEvent(*name, *object)); |
644 } | 643 } |
645 | 644 |
646 bool can_be_inlined = | 645 bool can_be_inlined = |
647 FLAG_use_ic && | 646 FLAG_use_ic && |
648 state == PREMONOMORPHIC && | 647 state == PREMONOMORPHIC && |
649 lookup.IsProperty() && | 648 lookup.IsProperty() && |
650 lookup.IsLoaded() && | |
651 lookup.IsCacheable() && | 649 lookup.IsCacheable() && |
652 lookup.holder() == *object && | 650 lookup.holder() == *object && |
653 lookup.type() == FIELD && | 651 lookup.type() == FIELD && |
654 !object->IsAccessCheckNeeded(); | 652 !object->IsAccessCheckNeeded(); |
655 | 653 |
656 if (can_be_inlined) { | 654 if (can_be_inlined) { |
657 Map* map = lookup.holder()->map(); | 655 Map* map = lookup.holder()->map(); |
658 // Property's index in the properties array. If negative we have | 656 // Property's index in the properties array. If negative we have |
659 // an inobject property. | 657 // an inobject property. |
660 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 658 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
661 if (index < 0) { | 659 if (index < 0) { |
662 // Index is an offset from the end of the object. | 660 // Index is an offset from the end of the object. |
663 int offset = map->instance_size() + (index * kPointerSize); | 661 int offset = map->instance_size() + (index * kPointerSize); |
664 if (PatchInlinedLoad(address(), map, offset)) { | 662 if (PatchInlinedLoad(address(), map, offset)) { |
665 set_target(megamorphic_stub()); | 663 set_target(megamorphic_stub()); |
666 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | 664 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
667 } | 665 } |
668 } | 666 } |
669 } | 667 } |
670 | 668 |
671 // Update inline cache and stub cache. | 669 // Update inline cache and stub cache. |
672 if (FLAG_use_ic && lookup.IsLoaded()) { | 670 if (FLAG_use_ic) { |
673 UpdateCaches(&lookup, state, object, name); | 671 UpdateCaches(&lookup, state, object, name); |
674 } | 672 } |
675 | 673 |
676 PropertyAttributes attr; | 674 PropertyAttributes attr; |
677 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 675 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
678 // Get the property. | 676 // Get the property. |
679 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 677 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
680 if (result->IsFailure()) return result; | 678 if (result->IsFailure()) return result; |
681 // If the property is not present, check if we need to throw an | 679 // If the property is not present, check if we need to throw an |
682 // exception. | 680 // exception. |
683 if (attr == ABSENT && IsContextual(object)) { | 681 if (attr == ABSENT && IsContextual(object)) { |
684 return ReferenceError("not_defined", name); | 682 return ReferenceError("not_defined", name); |
685 } | 683 } |
686 return result; | 684 return result; |
687 } | 685 } |
688 | 686 |
689 // Get the property. | 687 // Get the property. |
690 return object->GetProperty(*object, &lookup, *name, &attr); | 688 return object->GetProperty(*object, &lookup, *name, &attr); |
691 } | 689 } |
692 | 690 |
693 | 691 |
694 void LoadIC::UpdateCaches(LookupResult* lookup, | 692 void LoadIC::UpdateCaches(LookupResult* lookup, |
695 State state, | 693 State state, |
696 Handle<Object> object, | 694 Handle<Object> object, |
697 Handle<String> name) { | 695 Handle<String> name) { |
698 ASSERT(lookup->IsLoaded()); | |
699 // Bail out if we didn't find a result. | 696 // Bail out if we didn't find a result. |
700 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 697 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
701 | 698 |
702 // Loading properties from values is not common, so don't try to | 699 // Loading properties from values is not common, so don't try to |
703 // deal with non-JS objects here. | 700 // deal with non-JS objects here. |
704 if (!object->IsJSObject()) return; | 701 if (!object->IsJSObject()) return; |
705 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 702 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
706 | 703 |
707 // Compute the code stub for this load. | 704 // Compute the code stub for this load. |
708 Object* code = NULL; | 705 Object* code = NULL; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 LookupResult lookup; | 847 LookupResult lookup; |
851 LookupForRead(*object, *name, &lookup); | 848 LookupForRead(*object, *name, &lookup); |
852 | 849 |
853 // If we did not find a property, check if we need to throw an exception. | 850 // If we did not find a property, check if we need to throw an exception. |
854 if (!lookup.IsProperty()) { | 851 if (!lookup.IsProperty()) { |
855 if (FLAG_strict || IsContextual(object)) { | 852 if (FLAG_strict || IsContextual(object)) { |
856 return ReferenceError("not_defined", name); | 853 return ReferenceError("not_defined", name); |
857 } | 854 } |
858 } | 855 } |
859 | 856 |
860 if (FLAG_use_ic && lookup.IsLoaded()) { | 857 if (FLAG_use_ic) { |
861 UpdateCaches(&lookup, state, object, name); | 858 UpdateCaches(&lookup, state, object, name); |
862 } | 859 } |
863 | 860 |
864 PropertyAttributes attr; | 861 PropertyAttributes attr; |
865 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 862 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
866 // Get the property. | 863 // Get the property. |
867 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 864 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
868 if (result->IsFailure()) return result; | 865 if (result->IsFailure()) return result; |
869 // 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 |
870 // exception. | 867 // exception. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 } | 902 } |
906 } | 903 } |
907 | 904 |
908 // Get the property. | 905 // Get the property. |
909 return Runtime::GetObjectProperty(object, key); | 906 return Runtime::GetObjectProperty(object, key); |
910 } | 907 } |
911 | 908 |
912 | 909 |
913 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 910 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, |
914 Handle<Object> object, Handle<String> name) { | 911 Handle<Object> object, Handle<String> name) { |
915 ASSERT(lookup->IsLoaded()); | |
916 // Bail out if we didn't find a result. | 912 // Bail out if we didn't find a result. |
917 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 913 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
918 | 914 |
919 if (!object->IsJSObject()) return; | 915 if (!object->IsJSObject()) return; |
920 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 916 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
921 | 917 |
922 // Compute the code stub for this load. | 918 // Compute the code stub for this load. |
923 Object* code = NULL; | 919 Object* code = NULL; |
924 | 920 |
925 if (state == UNINITIALIZED) { | 921 if (state == UNINITIALIZED) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 | 982 |
987 | 983 |
988 static bool StoreICableLookup(LookupResult* lookup) { | 984 static bool StoreICableLookup(LookupResult* lookup) { |
989 // Bail out if we didn't find a result. | 985 // Bail out if we didn't find a result. |
990 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; | 986 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; |
991 | 987 |
992 // If the property is read-only, we leave the IC in its current | 988 // If the property is read-only, we leave the IC in its current |
993 // state. | 989 // state. |
994 if (lookup->IsReadOnly()) return false; | 990 if (lookup->IsReadOnly()) return false; |
995 | 991 |
996 if (!lookup->IsLoaded()) return false; | |
997 | |
998 return true; | 992 return true; |
999 } | 993 } |
1000 | 994 |
1001 | 995 |
1002 static bool LookupForWrite(JSObject* object, | 996 static bool LookupForWrite(JSObject* object, |
1003 String* name, | 997 String* name, |
1004 LookupResult* lookup) { | 998 LookupResult* lookup) { |
1005 object->LocalLookup(name, lookup); | 999 object->LocalLookup(name, lookup); |
1006 if (!StoreICableLookup(lookup)) { | 1000 if (!StoreICableLookup(lookup)) { |
1007 return false; | 1001 return false; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 // Set the property. | 1060 // Set the property. |
1067 return receiver->SetProperty(*name, *value, NONE); | 1061 return receiver->SetProperty(*name, *value, NONE); |
1068 } | 1062 } |
1069 | 1063 |
1070 | 1064 |
1071 void StoreIC::UpdateCaches(LookupResult* lookup, | 1065 void StoreIC::UpdateCaches(LookupResult* lookup, |
1072 State state, | 1066 State state, |
1073 Handle<JSObject> receiver, | 1067 Handle<JSObject> receiver, |
1074 Handle<String> name, | 1068 Handle<String> name, |
1075 Handle<Object> value) { | 1069 Handle<Object> value) { |
1076 ASSERT(lookup->IsLoaded()); | |
1077 // Skip JSGlobalProxy. | 1070 // Skip JSGlobalProxy. |
1078 ASSERT(!receiver->IsJSGlobalProxy()); | 1071 ASSERT(!receiver->IsJSGlobalProxy()); |
1079 | 1072 |
1080 ASSERT(StoreICableLookup(lookup)); | 1073 ASSERT(StoreICableLookup(lookup)); |
1081 | 1074 |
1082 // If the property has a non-field type allowing map transitions | 1075 // If the property has a non-field type allowing map transitions |
1083 // where there is extra room in the object, we leave the IC in its | 1076 // where there is extra room in the object, we leave the IC in its |
1084 // current state. | 1077 // current state. |
1085 PropertyType type = lookup->type(); | 1078 PropertyType type = lookup->type(); |
1086 | 1079 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 Handle<Object> result = SetElement(receiver, index, value); | 1167 Handle<Object> result = SetElement(receiver, index, value); |
1175 if (result.is_null()) return Failure::Exception(); | 1168 if (result.is_null()) return Failure::Exception(); |
1176 return *value; | 1169 return *value; |
1177 } | 1170 } |
1178 | 1171 |
1179 // Lookup the property locally in the receiver. | 1172 // Lookup the property locally in the receiver. |
1180 LookupResult lookup; | 1173 LookupResult lookup; |
1181 receiver->LocalLookup(*name, &lookup); | 1174 receiver->LocalLookup(*name, &lookup); |
1182 | 1175 |
1183 // Update inline cache and stub cache. | 1176 // Update inline cache and stub cache. |
1184 if (FLAG_use_ic && lookup.IsLoaded()) { | 1177 if (FLAG_use_ic) { |
1185 UpdateCaches(&lookup, state, receiver, name, value); | 1178 UpdateCaches(&lookup, state, receiver, name, value); |
1186 } | 1179 } |
1187 | 1180 |
1188 // Set the property. | 1181 // Set the property. |
1189 return receiver->SetProperty(*name, *value, NONE); | 1182 return receiver->SetProperty(*name, *value, NONE); |
1190 } | 1183 } |
1191 | 1184 |
1192 // Do not use ICs for objects that require access checks (including | 1185 // Do not use ICs for objects that require access checks (including |
1193 // the global object). | 1186 // the global object). |
1194 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1187 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
(...skipping 13 matching lines...) Expand all Loading... |
1208 // Set the property. | 1201 // Set the property. |
1209 return Runtime::SetObjectProperty(object, key, value, NONE); | 1202 return Runtime::SetObjectProperty(object, key, value, NONE); |
1210 } | 1203 } |
1211 | 1204 |
1212 | 1205 |
1213 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1206 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
1214 State state, | 1207 State state, |
1215 Handle<JSObject> receiver, | 1208 Handle<JSObject> receiver, |
1216 Handle<String> name, | 1209 Handle<String> name, |
1217 Handle<Object> value) { | 1210 Handle<Object> value) { |
1218 ASSERT(lookup->IsLoaded()); | |
1219 | |
1220 // Skip JSGlobalProxy. | 1211 // Skip JSGlobalProxy. |
1221 if (receiver->IsJSGlobalProxy()) return; | 1212 if (receiver->IsJSGlobalProxy()) return; |
1222 | 1213 |
1223 // Bail out if we didn't find a result. | 1214 // Bail out if we didn't find a result. |
1224 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return; | 1215 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return; |
1225 | 1216 |
1226 // If the property is read-only, we leave the IC in its current | 1217 // If the property is read-only, we leave the IC in its current |
1227 // state. | 1218 // state. |
1228 if (lookup->IsReadOnly()) return; | 1219 if (lookup->IsReadOnly()) return; |
1229 | 1220 |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 #undef ADDR | 1512 #undef ADDR |
1522 }; | 1513 }; |
1523 | 1514 |
1524 | 1515 |
1525 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1516 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
1526 return IC_utilities[id]; | 1517 return IC_utilities[id]; |
1527 } | 1518 } |
1528 | 1519 |
1529 | 1520 |
1530 } } // namespace v8::internal | 1521 } } // namespace v8::internal |
OLD | NEW |