| 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 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 | 358 |
| 359 if (!lookup.IsValid()) { | 359 if (!lookup.IsValid()) { |
| 360 // If the object does not have the requested property, check which | 360 // If the object does not have the requested property, check which |
| 361 // exception we need to throw. | 361 // exception we need to throw. |
| 362 if (is_contextual()) { | 362 if (is_contextual()) { |
| 363 return ReferenceError("not_defined", name); | 363 return ReferenceError("not_defined", name); |
| 364 } | 364 } |
| 365 return TypeError("undefined_method", object, name); | 365 return TypeError("undefined_method", object, name); |
| 366 } | 366 } |
| 367 | 367 |
| 368 // TODO(X64): Enable inline cache for calls. |
| 369 #ifndef V8_TARGET_ARCH_X64 |
| 368 // Lookup is valid: Update inline cache and stub cache. | 370 // Lookup is valid: Update inline cache and stub cache. |
| 369 if (FLAG_use_ic && lookup.IsLoaded()) { | 371 if (FLAG_use_ic && lookup.IsLoaded()) { |
| 370 UpdateCaches(&lookup, state, object, name); | 372 UpdateCaches(&lookup, state, object, name); |
| 371 } | 373 } |
| 374 #endif |
| 372 | 375 |
| 373 // Get the property. | 376 // Get the property. |
| 374 PropertyAttributes attr; | 377 PropertyAttributes attr; |
| 375 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 378 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 376 if (result->IsFailure()) return result; | 379 if (result->IsFailure()) return result; |
| 377 if (lookup.type() == INTERCEPTOR) { | 380 if (lookup.type() == INTERCEPTOR) { |
| 378 // If the object does not have the requested property, check which | 381 // If the object does not have the requested property, check which |
| 379 // exception we need to throw. | 382 // exception we need to throw. |
| 380 if (attr == ABSENT) { | 383 if (attr == ABSENT) { |
| 381 if (is_contextual()) { | 384 if (is_contextual()) { |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 if (index < 0) { | 605 if (index < 0) { |
| 603 // Index is an offset from the end of the object. | 606 // Index is an offset from the end of the object. |
| 604 int offset = map->instance_size() + (index * kPointerSize); | 607 int offset = map->instance_size() + (index * kPointerSize); |
| 605 if (PatchInlinedLoad(address(), map, offset)) { | 608 if (PatchInlinedLoad(address(), map, offset)) { |
| 606 set_target(megamorphic_stub()); | 609 set_target(megamorphic_stub()); |
| 607 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | 610 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
| 608 } | 611 } |
| 609 } | 612 } |
| 610 } | 613 } |
| 611 | 614 |
| 615 // TODO(X64): Enable inline cache for load. |
| 616 #ifndef V8_TARGET_ARCH_X64 |
| 612 // Update inline cache and stub cache. | 617 // Update inline cache and stub cache. |
| 613 if (FLAG_use_ic && lookup.IsLoaded()) { | 618 if (FLAG_use_ic && lookup.IsLoaded()) { |
| 614 UpdateCaches(&lookup, state, object, name); | 619 UpdateCaches(&lookup, state, object, name); |
| 615 } | 620 } |
| 621 #endif |
| 616 | 622 |
| 617 PropertyAttributes attr; | 623 PropertyAttributes attr; |
| 618 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { | 624 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { |
| 619 // Get the property. | 625 // Get the property. |
| 620 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 626 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 621 if (result->IsFailure()) return result; | 627 if (result->IsFailure()) return result; |
| 622 // If the property is not present, check if we need to throw an | 628 // If the property is not present, check if we need to throw an |
| 623 // exception. | 629 // exception. |
| 624 if (attr == ABSENT && is_contextual()) { | 630 if (attr == ABSENT && is_contextual()) { |
| 625 return ReferenceError("not_defined", name); | 631 return ReferenceError("not_defined", name); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 Handle<Object> key) { | 736 Handle<Object> key) { |
| 731 if (key->IsSymbol()) { | 737 if (key->IsSymbol()) { |
| 732 Handle<String> name = Handle<String>::cast(key); | 738 Handle<String> name = Handle<String>::cast(key); |
| 733 | 739 |
| 734 // If the object is undefined or null it's illegal to try to get any | 740 // If the object is undefined or null it's illegal to try to get any |
| 735 // of its properties; throw a TypeError in that case. | 741 // of its properties; throw a TypeError in that case. |
| 736 if (object->IsUndefined() || object->IsNull()) { | 742 if (object->IsUndefined() || object->IsNull()) { |
| 737 return TypeError("non_object_property_load", object, name); | 743 return TypeError("non_object_property_load", object, name); |
| 738 } | 744 } |
| 739 | 745 |
| 740 if (FLAG_use_ic) { | 746 // TODO(X64): Enable specialized stubs for length and prototype lookup. |
| 747 #ifndef V8_TARGET_ARCH_X64 |
| 748 if (false && FLAG_use_ic) { |
| 741 // Use specialized code for getting the length of strings. | 749 // Use specialized code for getting the length of strings. |
| 742 if (object->IsString() && name->Equals(Heap::length_symbol())) { | 750 if (object->IsString() && name->Equals(Heap::length_symbol())) { |
| 743 Handle<String> string = Handle<String>::cast(object); | 751 Handle<String> string = Handle<String>::cast(object); |
| 744 Object* code = NULL; | 752 Object* code = NULL; |
| 745 code = StubCache::ComputeKeyedLoadStringLength(*name, *string); | 753 code = StubCache::ComputeKeyedLoadStringLength(*name, *string); |
| 746 if (code->IsFailure()) return code; | 754 if (code->IsFailure()) return code; |
| 747 set_target(Code::cast(code)); | 755 set_target(Code::cast(code)); |
| 748 #ifdef DEBUG | 756 #ifdef DEBUG |
| 749 TraceIC("KeyedLoadIC", name, state, target()); | 757 TraceIC("KeyedLoadIC", name, state, target()); |
| 750 #endif | 758 #endif // DEBUG |
| 751 return Smi::FromInt(string->length()); | 759 return Smi::FromInt(string->length()); |
| 752 } | 760 } |
| 753 | 761 |
| 754 // Use specialized code for getting the length of arrays. | 762 // Use specialized code for getting the length of arrays. |
| 755 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { | 763 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { |
| 756 Handle<JSArray> array = Handle<JSArray>::cast(object); | 764 Handle<JSArray> array = Handle<JSArray>::cast(object); |
| 757 Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array); | 765 Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array); |
| 758 if (code->IsFailure()) return code; | 766 if (code->IsFailure()) return code; |
| 759 set_target(Code::cast(code)); | 767 set_target(Code::cast(code)); |
| 760 #ifdef DEBUG | 768 #ifdef DEBUG |
| 761 TraceIC("KeyedLoadIC", name, state, target()); | 769 TraceIC("KeyedLoadIC", name, state, target()); |
| 762 #endif | 770 #endif // DEBUG |
| 763 return JSArray::cast(*object)->length(); | 771 return JSArray::cast(*object)->length(); |
| 764 } | 772 } |
| 765 | 773 |
| 766 // Use specialized code for getting prototype of functions. | 774 // Use specialized code for getting prototype of functions. |
| 767 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) { | 775 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) { |
| 768 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 776 Handle<JSFunction> function = Handle<JSFunction>::cast(object); |
| 769 Object* code = | 777 Object* code = |
| 770 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); | 778 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); |
| 771 if (code->IsFailure()) return code; | 779 if (code->IsFailure()) return code; |
| 772 set_target(Code::cast(code)); | 780 set_target(Code::cast(code)); |
| 773 #ifdef DEBUG | 781 #ifdef DEBUG |
| 774 TraceIC("KeyedLoadIC", name, state, target()); | 782 TraceIC("KeyedLoadIC", name, state, target()); |
| 775 #endif | 783 #endif // DEBUG |
| 776 return Accessors::FunctionGetPrototype(*object, 0); | 784 return Accessors::FunctionGetPrototype(*object, 0); |
| 777 } | 785 } |
| 778 } | 786 } |
| 787 #endif // !V8_TARGET_ARCH_X64 |
| 779 | 788 |
| 780 // Check if the name is trivially convertible to an index and get | 789 // Check if the name is trivially convertible to an index and get |
| 781 // the element or char if so. | 790 // the element or char if so. |
| 782 uint32_t index = 0; | 791 uint32_t index = 0; |
| 783 if (name->AsArrayIndex(&index)) { | 792 if (name->AsArrayIndex(&index)) { |
| 784 HandleScope scope; | 793 HandleScope scope; |
| 785 // Rewrite to the generic keyed load stub. | 794 // Rewrite to the generic keyed load stub. |
| 786 if (FLAG_use_ic) set_target(generic_stub()); | 795 if (FLAG_use_ic) set_target(generic_stub()); |
| 787 return Runtime::GetElementOrCharAt(object, index); | 796 return Runtime::GetElementOrCharAt(object, index); |
| 788 } | 797 } |
| 789 | 798 |
| 790 // Named lookup. | 799 // Named lookup. |
| 791 LookupResult lookup; | 800 LookupResult lookup; |
| 792 LookupForRead(*object, *name, &lookup); | 801 LookupForRead(*object, *name, &lookup); |
| 793 | 802 |
| 794 // If lookup is invalid, check if we need to throw an exception. | 803 // If lookup is invalid, check if we need to throw an exception. |
| 795 if (!lookup.IsValid()) { | 804 if (!lookup.IsValid()) { |
| 796 if (FLAG_strict || is_contextual()) { | 805 if (FLAG_strict || is_contextual()) { |
| 797 return ReferenceError("not_defined", name); | 806 return ReferenceError("not_defined", name); |
| 798 } | 807 } |
| 799 } | 808 } |
| 800 | 809 |
| 810 // TODO(X64): Enable inline caching for load. |
| 811 #ifndef V8_TARGET_ARCH_X64 |
| 801 // Update the inline cache. | 812 // Update the inline cache. |
| 802 if (FLAG_use_ic && lookup.IsLoaded()) { | 813 if (FLAG_use_ic && lookup.IsLoaded()) { |
| 803 UpdateCaches(&lookup, state, object, name); | 814 UpdateCaches(&lookup, state, object, name); |
| 804 } | 815 } |
| 816 #endif |
| 805 | 817 |
| 806 PropertyAttributes attr; | 818 PropertyAttributes attr; |
| 807 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { | 819 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { |
| 808 // Get the property. | 820 // Get the property. |
| 809 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 821 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 810 if (result->IsFailure()) return result; | 822 if (result->IsFailure()) return result; |
| 811 // If the property is not present, check if we need to throw an | 823 // If the property is not present, check if we need to throw an |
| 812 // exception. | 824 // exception. |
| 813 if (attr == ABSENT && is_contextual()) { | 825 if (attr == ABSENT && is_contextual()) { |
| 814 return ReferenceError("not_defined", name); | 826 return ReferenceError("not_defined", name); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 | 977 |
| 966 // Check if the given name is an array index. | 978 // Check if the given name is an array index. |
| 967 uint32_t index; | 979 uint32_t index; |
| 968 if (name->AsArrayIndex(&index)) { | 980 if (name->AsArrayIndex(&index)) { |
| 969 HandleScope scope; | 981 HandleScope scope; |
| 970 Handle<Object> result = SetElement(receiver, index, value); | 982 Handle<Object> result = SetElement(receiver, index, value); |
| 971 if (result.is_null()) return Failure::Exception(); | 983 if (result.is_null()) return Failure::Exception(); |
| 972 return *value; | 984 return *value; |
| 973 } | 985 } |
| 974 | 986 |
| 987 // TODO(X64): Enable inline cache for StoreIC. |
| 988 #ifdef V8_TARGET_ARCH_X64 |
| 989 USE(&LookupForWrite); // The compiler complains otherwise. |
| 990 #else |
| 975 // Lookup the property locally in the receiver. | 991 // Lookup the property locally in the receiver. |
| 976 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 992 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
| 977 LookupResult lookup; | 993 LookupResult lookup; |
| 978 if (LookupForWrite(*receiver, *name, &lookup)) { | 994 if (LookupForWrite(*receiver, *name, &lookup)) { |
| 979 UpdateCaches(&lookup, state, receiver, name, value); | 995 UpdateCaches(&lookup, state, receiver, name, value); |
| 980 } | 996 } |
| 981 } | 997 } |
| 998 #endif |
| 982 | 999 |
| 983 // Set the property. | 1000 // Set the property. |
| 984 return receiver->SetProperty(*name, *value, NONE); | 1001 return receiver->SetProperty(*name, *value, NONE); |
| 985 } | 1002 } |
| 986 | 1003 |
| 987 | 1004 |
| 988 void StoreIC::UpdateCaches(LookupResult* lookup, | 1005 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 989 State state, | 1006 State state, |
| 990 Handle<JSObject> receiver, | 1007 Handle<JSObject> receiver, |
| 991 Handle<String> name, | 1008 Handle<String> name, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 HandleScope scope; | 1107 HandleScope scope; |
| 1091 Handle<Object> result = SetElement(receiver, index, value); | 1108 Handle<Object> result = SetElement(receiver, index, value); |
| 1092 if (result.is_null()) return Failure::Exception(); | 1109 if (result.is_null()) return Failure::Exception(); |
| 1093 return *value; | 1110 return *value; |
| 1094 } | 1111 } |
| 1095 | 1112 |
| 1096 // Lookup the property locally in the receiver. | 1113 // Lookup the property locally in the receiver. |
| 1097 LookupResult lookup; | 1114 LookupResult lookup; |
| 1098 receiver->LocalLookup(*name, &lookup); | 1115 receiver->LocalLookup(*name, &lookup); |
| 1099 | 1116 |
| 1117 // TODO(X64): Enable inline cache for KeyedStoreIC. |
| 1118 #ifndef V8_TARGET_ARCH_X64 |
| 1100 // Update inline cache and stub cache. | 1119 // Update inline cache and stub cache. |
| 1101 if (FLAG_use_ic && lookup.IsLoaded()) { | 1120 if (FLAG_use_ic && lookup.IsLoaded()) { |
| 1102 UpdateCaches(&lookup, state, receiver, name, value); | 1121 UpdateCaches(&lookup, state, receiver, name, value); |
| 1103 } | 1122 } |
| 1123 #endif |
| 1104 | 1124 |
| 1105 // Set the property. | 1125 // Set the property. |
| 1106 return receiver->SetProperty(*name, *value, NONE); | 1126 return receiver->SetProperty(*name, *value, NONE); |
| 1107 } | 1127 } |
| 1108 | 1128 |
| 1109 // Do not use ICs for objects that require access checks (including | 1129 // Do not use ICs for objects that require access checks (including |
| 1110 // the global object). | 1130 // the global object). |
| 1111 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1131 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 1112 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1132 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 1113 | 1133 |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1365 #undef ADDR | 1385 #undef ADDR |
| 1366 }; | 1386 }; |
| 1367 | 1387 |
| 1368 | 1388 |
| 1369 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1389 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 1370 return IC_utilities[id]; | 1390 return IC_utilities[id]; |
| 1371 } | 1391 } |
| 1372 | 1392 |
| 1373 | 1393 |
| 1374 } } // namespace v8::internal | 1394 } } // namespace v8::internal |
| OLD | NEW |