| 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 |