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 |