| 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 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 if (!lookup.IsValid()) { | 425 if (!lookup.IsValid()) { |
| 426 // If the object does not have the requested property, check which | 426 // If the object does not have the requested property, check which |
| 427 // exception we need to throw. | 427 // exception we need to throw. |
| 428 if (IsContextual(object)) { | 428 if (IsContextual(object)) { |
| 429 return ReferenceError("not_defined", name); | 429 return ReferenceError("not_defined", name); |
| 430 } | 430 } |
| 431 return TypeError("undefined_method", object, name); | 431 return TypeError("undefined_method", object, name); |
| 432 } | 432 } |
| 433 | 433 |
| 434 // Lookup is valid: Update inline cache and stub cache. | 434 // Lookup is valid: Update inline cache and stub cache. |
| 435 if (FLAG_use_ic && lookup.IsLoaded()) { | 435 if (FLAG_use_ic) { |
| 436 UpdateCaches(&lookup, state, object, name); | 436 UpdateCaches(&lookup, state, object, name); |
| 437 } | 437 } |
| 438 | 438 |
| 439 // Get the property. | 439 // Get the property. |
| 440 PropertyAttributes attr; | 440 PropertyAttributes attr; |
| 441 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 441 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 442 if (result->IsFailure()) return result; | 442 if (result->IsFailure()) return result; |
| 443 if (lookup.type() == INTERCEPTOR) { | 443 if (lookup.type() == INTERCEPTOR) { |
| 444 // If the object does not have the requested property, check which | 444 // If the object does not have the requested property, check which |
| 445 // exception we need to throw. | 445 // exception we need to throw. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 result = TryCallAsFunction(result); | 484 result = TryCallAsFunction(result); |
| 485 return result->IsJSFunction() ? | 485 return result->IsJSFunction() ? |
| 486 result : TypeError("property_not_function", object, name); | 486 result : TypeError("property_not_function", object, name); |
| 487 } | 487 } |
| 488 | 488 |
| 489 | 489 |
| 490 void CallIC::UpdateCaches(LookupResult* lookup, | 490 void CallIC::UpdateCaches(LookupResult* lookup, |
| 491 State state, | 491 State state, |
| 492 Handle<Object> object, | 492 Handle<Object> object, |
| 493 Handle<String> name) { | 493 Handle<String> name) { |
| 494 ASSERT(lookup->IsLoaded()); | |
| 495 // Bail out if we didn't find a result. | 494 // Bail out if we didn't find a result. |
| 496 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 495 if (!lookup->IsValid() || !lookup->IsCacheable()) return; |
| 497 | 496 |
| 498 // Compute the number of arguments. | 497 // Compute the number of arguments. |
| 499 int argc = target()->arguments_count(); | 498 int argc = target()->arguments_count(); |
| 500 InLoopFlag in_loop = target()->ic_in_loop(); | 499 InLoopFlag in_loop = target()->ic_in_loop(); |
| 501 Object* code = NULL; | 500 Object* code = NULL; |
| 502 | 501 |
| 503 if (state == UNINITIALIZED) { | 502 if (state == UNINITIALIZED) { |
| 504 // This is the first time we execute this inline cache. | 503 // This is the first time we execute this inline cache. |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 if (FLAG_strict || IsContextual(object)) { | 646 if (FLAG_strict || IsContextual(object)) { |
| 648 return ReferenceError("not_defined", name); | 647 return ReferenceError("not_defined", name); |
| 649 } | 648 } |
| 650 LOG(SuspectReadEvent(*name, *object)); | 649 LOG(SuspectReadEvent(*name, *object)); |
| 651 } | 650 } |
| 652 | 651 |
| 653 bool can_be_inlined = | 652 bool can_be_inlined = |
| 654 FLAG_use_ic && | 653 FLAG_use_ic && |
| 655 state == PREMONOMORPHIC && | 654 state == PREMONOMORPHIC && |
| 656 lookup.IsValid() && | 655 lookup.IsValid() && |
| 657 lookup.IsLoaded() && | |
| 658 lookup.IsCacheable() && | 656 lookup.IsCacheable() && |
| 659 lookup.holder() == *object && | 657 lookup.holder() == *object && |
| 660 lookup.type() == FIELD && | 658 lookup.type() == FIELD && |
| 661 !object->IsAccessCheckNeeded(); | 659 !object->IsAccessCheckNeeded(); |
| 662 | 660 |
| 663 if (can_be_inlined) { | 661 if (can_be_inlined) { |
| 664 Map* map = lookup.holder()->map(); | 662 Map* map = lookup.holder()->map(); |
| 665 // Property's index in the properties array. If negative we have | 663 // Property's index in the properties array. If negative we have |
| 666 // an inobject property. | 664 // an inobject property. |
| 667 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 665 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 668 if (index < 0) { | 666 if (index < 0) { |
| 669 // Index is an offset from the end of the object. | 667 // Index is an offset from the end of the object. |
| 670 int offset = map->instance_size() + (index * kPointerSize); | 668 int offset = map->instance_size() + (index * kPointerSize); |
| 671 if (PatchInlinedLoad(address(), map, offset)) { | 669 if (PatchInlinedLoad(address(), map, offset)) { |
| 672 set_target(megamorphic_stub()); | 670 set_target(megamorphic_stub()); |
| 673 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | 671 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
| 674 } | 672 } |
| 675 } | 673 } |
| 676 } | 674 } |
| 677 | 675 |
| 678 // Update inline cache and stub cache. | 676 // Update inline cache and stub cache. |
| 679 if (FLAG_use_ic && lookup.IsLoaded()) { | 677 if (FLAG_use_ic) { |
| 680 UpdateCaches(&lookup, state, object, name); | 678 UpdateCaches(&lookup, state, object, name); |
| 681 } | 679 } |
| 682 | 680 |
| 683 PropertyAttributes attr; | 681 PropertyAttributes attr; |
| 684 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { | 682 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { |
| 685 // Get the property. | 683 // Get the property. |
| 686 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 684 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 687 if (result->IsFailure()) return result; | 685 if (result->IsFailure()) return result; |
| 688 // If the property is not present, check if we need to throw an | 686 // If the property is not present, check if we need to throw an |
| 689 // exception. | 687 // exception. |
| 690 if (attr == ABSENT && IsContextual(object)) { | 688 if (attr == ABSENT && IsContextual(object)) { |
| 691 return ReferenceError("not_defined", name); | 689 return ReferenceError("not_defined", name); |
| 692 } | 690 } |
| 693 return result; | 691 return result; |
| 694 } | 692 } |
| 695 | 693 |
| 696 // Get the property. | 694 // Get the property. |
| 697 return object->GetProperty(*object, &lookup, *name, &attr); | 695 return object->GetProperty(*object, &lookup, *name, &attr); |
| 698 } | 696 } |
| 699 | 697 |
| 700 | 698 |
| 701 void LoadIC::UpdateCaches(LookupResult* lookup, | 699 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 702 State state, | 700 State state, |
| 703 Handle<Object> object, | 701 Handle<Object> object, |
| 704 Handle<String> name) { | 702 Handle<String> name) { |
| 705 ASSERT(lookup->IsLoaded()); | |
| 706 // Bail out if we didn't find a result. | 703 // Bail out if we didn't find a result. |
| 707 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 704 if (!lookup->IsValid() || !lookup->IsCacheable()) return; |
| 708 | 705 |
| 709 // Loading properties from values is not common, so don't try to | 706 // Loading properties from values is not common, so don't try to |
| 710 // deal with non-JS objects here. | 707 // deal with non-JS objects here. |
| 711 if (!object->IsJSObject()) return; | 708 if (!object->IsJSObject()) return; |
| 712 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 709 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 713 | 710 |
| 714 // Compute the code stub for this load. | 711 // Compute the code stub for this load. |
| 715 Object* code = NULL; | 712 Object* code = NULL; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 LookupResult lookup; | 854 LookupResult lookup; |
| 858 LookupForRead(*object, *name, &lookup); | 855 LookupForRead(*object, *name, &lookup); |
| 859 | 856 |
| 860 // If lookup is invalid, check if we need to throw an exception. | 857 // If lookup is invalid, check if we need to throw an exception. |
| 861 if (!lookup.IsValid()) { | 858 if (!lookup.IsValid()) { |
| 862 if (FLAG_strict || IsContextual(object)) { | 859 if (FLAG_strict || IsContextual(object)) { |
| 863 return ReferenceError("not_defined", name); | 860 return ReferenceError("not_defined", name); |
| 864 } | 861 } |
| 865 } | 862 } |
| 866 | 863 |
| 867 if (FLAG_use_ic && lookup.IsLoaded()) { | 864 if (FLAG_use_ic) { |
| 868 UpdateCaches(&lookup, state, object, name); | 865 UpdateCaches(&lookup, state, object, name); |
| 869 } | 866 } |
| 870 | 867 |
| 871 PropertyAttributes attr; | 868 PropertyAttributes attr; |
| 872 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { | 869 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { |
| 873 // Get the property. | 870 // Get the property. |
| 874 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 871 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 875 if (result->IsFailure()) return result; | 872 if (result->IsFailure()) return result; |
| 876 // If the property is not present, check if we need to throw an | 873 // If the property is not present, check if we need to throw an |
| 877 // exception. | 874 // exception. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 } | 907 } |
| 911 } | 908 } |
| 912 | 909 |
| 913 // Get the property. | 910 // Get the property. |
| 914 return Runtime::GetObjectProperty(object, key); | 911 return Runtime::GetObjectProperty(object, key); |
| 915 } | 912 } |
| 916 | 913 |
| 917 | 914 |
| 918 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 915 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, |
| 919 Handle<Object> object, Handle<String> name) { | 916 Handle<Object> object, Handle<String> name) { |
| 920 ASSERT(lookup->IsLoaded()); | |
| 921 // Bail out if we didn't find a result. | 917 // Bail out if we didn't find a result. |
| 922 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 918 if (!lookup->IsValid() || !lookup->IsCacheable()) return; |
| 923 | 919 |
| 924 if (!object->IsJSObject()) return; | 920 if (!object->IsJSObject()) return; |
| 925 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 921 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 926 | 922 |
| 927 // Compute the code stub for this load. | 923 // Compute the code stub for this load. |
| 928 Object* code = NULL; | 924 Object* code = NULL; |
| 929 | 925 |
| 930 if (state == UNINITIALIZED) { | 926 if (state == UNINITIALIZED) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 | 987 |
| 992 | 988 |
| 993 static bool StoreICableLookup(LookupResult* lookup) { | 989 static bool StoreICableLookup(LookupResult* lookup) { |
| 994 // Bail out if we didn't find a result. | 990 // Bail out if we didn't find a result. |
| 995 if (!lookup->IsValid() || !lookup->IsCacheable()) return false; | 991 if (!lookup->IsValid() || !lookup->IsCacheable()) return false; |
| 996 | 992 |
| 997 // If the property is read-only, we leave the IC in its current | 993 // If the property is read-only, we leave the IC in its current |
| 998 // state. | 994 // state. |
| 999 if (lookup->IsReadOnly()) return false; | 995 if (lookup->IsReadOnly()) return false; |
| 1000 | 996 |
| 1001 if (!lookup->IsLoaded()) return false; | |
| 1002 | |
| 1003 return true; | 997 return true; |
| 1004 } | 998 } |
| 1005 | 999 |
| 1006 | 1000 |
| 1007 static bool LookupForWrite(JSObject* object, | 1001 static bool LookupForWrite(JSObject* object, |
| 1008 String* name, | 1002 String* name, |
| 1009 LookupResult* lookup) { | 1003 LookupResult* lookup) { |
| 1010 object->LocalLookup(name, lookup); | 1004 object->LocalLookup(name, lookup); |
| 1011 if (!StoreICableLookup(lookup)) { | 1005 if (!StoreICableLookup(lookup)) { |
| 1012 return false; | 1006 return false; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1057 // Set the property. | 1051 // Set the property. |
| 1058 return receiver->SetProperty(*name, *value, NONE); | 1052 return receiver->SetProperty(*name, *value, NONE); |
| 1059 } | 1053 } |
| 1060 | 1054 |
| 1061 | 1055 |
| 1062 void StoreIC::UpdateCaches(LookupResult* lookup, | 1056 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1063 State state, | 1057 State state, |
| 1064 Handle<JSObject> receiver, | 1058 Handle<JSObject> receiver, |
| 1065 Handle<String> name, | 1059 Handle<String> name, |
| 1066 Handle<Object> value) { | 1060 Handle<Object> value) { |
| 1067 ASSERT(lookup->IsLoaded()); | |
| 1068 // Skip JSGlobalProxy. | 1061 // Skip JSGlobalProxy. |
| 1069 ASSERT(!receiver->IsJSGlobalProxy()); | 1062 ASSERT(!receiver->IsJSGlobalProxy()); |
| 1070 | 1063 |
| 1071 ASSERT(StoreICableLookup(lookup)); | 1064 ASSERT(StoreICableLookup(lookup)); |
| 1072 | 1065 |
| 1073 // If the property has a non-field type allowing map transitions | 1066 // If the property has a non-field type allowing map transitions |
| 1074 // where there is extra room in the object, we leave the IC in its | 1067 // where there is extra room in the object, we leave the IC in its |
| 1075 // current state. | 1068 // current state. |
| 1076 PropertyType type = lookup->type(); | 1069 PropertyType type = lookup->type(); |
| 1077 | 1070 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1165 Handle<Object> result = SetElement(receiver, index, value); | 1158 Handle<Object> result = SetElement(receiver, index, value); |
| 1166 if (result.is_null()) return Failure::Exception(); | 1159 if (result.is_null()) return Failure::Exception(); |
| 1167 return *value; | 1160 return *value; |
| 1168 } | 1161 } |
| 1169 | 1162 |
| 1170 // Lookup the property locally in the receiver. | 1163 // Lookup the property locally in the receiver. |
| 1171 LookupResult lookup; | 1164 LookupResult lookup; |
| 1172 receiver->LocalLookup(*name, &lookup); | 1165 receiver->LocalLookup(*name, &lookup); |
| 1173 | 1166 |
| 1174 // Update inline cache and stub cache. | 1167 // Update inline cache and stub cache. |
| 1175 if (FLAG_use_ic && lookup.IsLoaded()) { | 1168 if (FLAG_use_ic) { |
| 1176 UpdateCaches(&lookup, state, receiver, name, value); | 1169 UpdateCaches(&lookup, state, receiver, name, value); |
| 1177 } | 1170 } |
| 1178 | 1171 |
| 1179 // Set the property. | 1172 // Set the property. |
| 1180 return receiver->SetProperty(*name, *value, NONE); | 1173 return receiver->SetProperty(*name, *value, NONE); |
| 1181 } | 1174 } |
| 1182 | 1175 |
| 1183 // Do not use ICs for objects that require access checks (including | 1176 // Do not use ICs for objects that require access checks (including |
| 1184 // the global object). | 1177 // the global object). |
| 1185 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1178 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1199 // Set the property. | 1192 // Set the property. |
| 1200 return Runtime::SetObjectProperty(object, key, value, NONE); | 1193 return Runtime::SetObjectProperty(object, key, value, NONE); |
| 1201 } | 1194 } |
| 1202 | 1195 |
| 1203 | 1196 |
| 1204 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1197 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
| 1205 State state, | 1198 State state, |
| 1206 Handle<JSObject> receiver, | 1199 Handle<JSObject> receiver, |
| 1207 Handle<String> name, | 1200 Handle<String> name, |
| 1208 Handle<Object> value) { | 1201 Handle<Object> value) { |
| 1209 ASSERT(lookup->IsLoaded()); | |
| 1210 | |
| 1211 // Skip JSGlobalProxy. | 1202 // Skip JSGlobalProxy. |
| 1212 if (receiver->IsJSGlobalProxy()) return; | 1203 if (receiver->IsJSGlobalProxy()) return; |
| 1213 | 1204 |
| 1214 // Bail out if we didn't find a result. | 1205 // Bail out if we didn't find a result. |
| 1215 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 1206 if (!lookup->IsValid() || !lookup->IsCacheable()) return; |
| 1216 | 1207 |
| 1217 // If the property is read-only, we leave the IC in its current | 1208 // If the property is read-only, we leave the IC in its current |
| 1218 // state. | 1209 // state. |
| 1219 if (lookup->IsReadOnly()) return; | 1210 if (lookup->IsReadOnly()) return; |
| 1220 | 1211 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 #undef ADDR | 1414 #undef ADDR |
| 1424 }; | 1415 }; |
| 1425 | 1416 |
| 1426 | 1417 |
| 1427 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1418 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 1428 return IC_utilities[id]; | 1419 return IC_utilities[id]; |
| 1429 } | 1420 } |
| 1430 | 1421 |
| 1431 | 1422 |
| 1432 } } // namespace v8::internal | 1423 } } // namespace v8::internal |
| OLD | NEW |