OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 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 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 { | 628 { |
629 // Leaving JavaScript. | 629 // Leaving JavaScript. |
630 VMState state(EXTERNAL); | 630 VMState state(EXTERNAL); |
631 result = enum_fun(info); | 631 result = enum_fun(info); |
632 } | 632 } |
633 } | 633 } |
634 return result; | 634 return result; |
635 } | 635 } |
636 | 636 |
637 | 637 |
| 638 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
| 639 int len = array->length(); |
| 640 for (int i = 0; i < len; i++) { |
| 641 Object* e = array->get(i); |
| 642 if (!(e->IsString() || e->IsNumber())) return false; |
| 643 } |
| 644 return true; |
| 645 } |
| 646 |
| 647 |
638 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object, | 648 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object, |
639 KeyCollectionType type) { | 649 KeyCollectionType type) { |
| 650 USE(ContainsOnlyValidKeys); |
640 Handle<FixedArray> content = Factory::empty_fixed_array(); | 651 Handle<FixedArray> content = Factory::empty_fixed_array(); |
641 Handle<JSObject> arguments_boilerplate = | 652 Handle<JSObject> arguments_boilerplate = |
642 Handle<JSObject>( | 653 Handle<JSObject>( |
643 Top::context()->global_context()->arguments_boilerplate()); | 654 Top::context()->global_context()->arguments_boilerplate()); |
644 Handle<JSFunction> arguments_function = | 655 Handle<JSFunction> arguments_function = |
645 Handle<JSFunction>( | 656 Handle<JSFunction>( |
646 JSFunction::cast(arguments_boilerplate->map()->constructor())); | 657 JSFunction::cast(arguments_boilerplate->map()->constructor())); |
647 | 658 |
648 // Only collect keys if access is permitted. | 659 // Only collect keys if access is permitted. |
649 for (Handle<Object> p = object; | 660 for (Handle<Object> p = object; |
650 *p != Heap::null_value(); | 661 *p != Heap::null_value(); |
651 p = Handle<Object>(p->GetPrototype())) { | 662 p = Handle<Object>(p->GetPrototype())) { |
652 Handle<JSObject> current(JSObject::cast(*p)); | 663 Handle<JSObject> current(JSObject::cast(*p)); |
653 | 664 |
654 // Check access rights if required. | 665 // Check access rights if required. |
655 if (current->IsAccessCheckNeeded() && | 666 if (current->IsAccessCheckNeeded() && |
656 !Top::MayNamedAccess(*current, Heap::undefined_value(), | 667 !Top::MayNamedAccess(*current, Heap::undefined_value(), |
657 v8::ACCESS_KEYS)) { | 668 v8::ACCESS_KEYS)) { |
658 Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS); | 669 Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS); |
659 break; | 670 break; |
660 } | 671 } |
661 | 672 |
662 // Compute the element keys. | 673 // Compute the element keys. |
663 Handle<FixedArray> element_keys = | 674 Handle<FixedArray> element_keys = |
664 Factory::NewFixedArray(current->NumberOfEnumElements()); | 675 Factory::NewFixedArray(current->NumberOfEnumElements()); |
665 current->GetEnumElementKeys(*element_keys); | 676 current->GetEnumElementKeys(*element_keys); |
666 content = UnionOfKeys(content, element_keys); | 677 content = UnionOfKeys(content, element_keys); |
| 678 ASSERT(ContainsOnlyValidKeys(content)); |
667 | 679 |
668 // Add the element keys from the interceptor. | 680 // Add the element keys from the interceptor. |
669 if (current->HasIndexedInterceptor()) { | 681 if (current->HasIndexedInterceptor()) { |
670 v8::Handle<v8::Array> result = | 682 v8::Handle<v8::Array> result = |
671 GetKeysForIndexedInterceptor(object, current); | 683 GetKeysForIndexedInterceptor(object, current); |
672 if (!result.IsEmpty()) | 684 if (!result.IsEmpty()) |
673 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); | 685 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); |
| 686 ASSERT(ContainsOnlyValidKeys(content)); |
674 } | 687 } |
675 | 688 |
676 // We can cache the computed property keys if access checks are | 689 // We can cache the computed property keys if access checks are |
677 // not needed and no interceptors are involved. | 690 // not needed and no interceptors are involved. |
678 // | 691 // |
679 // We do not use the cache if the object has elements and | 692 // We do not use the cache if the object has elements and |
680 // therefore it does not make sense to cache the property names | 693 // therefore it does not make sense to cache the property names |
681 // for arguments objects. Arguments objects will always have | 694 // for arguments objects. Arguments objects will always have |
682 // elements. | 695 // elements. |
683 // Wrapped strings have elements, but don't have an elements | 696 // Wrapped strings have elements, but don't have an elements |
684 // array or dictionary. So the fast inline test for whether to | 697 // array or dictionary. So the fast inline test for whether to |
685 // use the cache says yes, so we should not create a cache. | 698 // use the cache says yes, so we should not create a cache. |
686 bool cache_enum_keys = | 699 bool cache_enum_keys = |
687 ((current->map()->constructor() != *arguments_function) && | 700 ((current->map()->constructor() != *arguments_function) && |
688 !current->IsJSValue() && | 701 !current->IsJSValue() && |
689 !current->IsAccessCheckNeeded() && | 702 !current->IsAccessCheckNeeded() && |
690 !current->HasNamedInterceptor() && | 703 !current->HasNamedInterceptor() && |
691 !current->HasIndexedInterceptor()); | 704 !current->HasIndexedInterceptor()); |
692 // Compute the property keys and cache them if possible. | 705 // Compute the property keys and cache them if possible. |
693 content = | 706 content = |
694 UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys)); | 707 UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys)); |
| 708 ASSERT(ContainsOnlyValidKeys(content)); |
695 | 709 |
696 // Add the property keys from the interceptor. | 710 // Add the property keys from the interceptor. |
697 if (current->HasNamedInterceptor()) { | 711 if (current->HasNamedInterceptor()) { |
698 v8::Handle<v8::Array> result = | 712 v8::Handle<v8::Array> result = |
699 GetKeysForNamedInterceptor(object, current); | 713 GetKeysForNamedInterceptor(object, current); |
700 if (!result.IsEmpty()) | 714 if (!result.IsEmpty()) |
701 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); | 715 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); |
| 716 ASSERT(ContainsOnlyValidKeys(content)); |
702 } | 717 } |
703 | 718 |
704 // If we only want local properties we bail out after the first | 719 // If we only want local properties we bail out after the first |
705 // iteration. | 720 // iteration. |
706 if (type == LOCAL_ONLY) | 721 if (type == LOCAL_ONLY) |
707 break; | 722 break; |
708 } | 723 } |
709 return content; | 724 return content; |
710 } | 725 } |
711 | 726 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 | 857 |
843 OptimizedObjectForAddingMultipleProperties:: | 858 OptimizedObjectForAddingMultipleProperties:: |
844 ~OptimizedObjectForAddingMultipleProperties() { | 859 ~OptimizedObjectForAddingMultipleProperties() { |
845 // Reoptimize the object to allow fast property access. | 860 // Reoptimize the object to allow fast property access. |
846 if (has_been_transformed_) { | 861 if (has_been_transformed_) { |
847 TransformToFastProperties(object_, unused_property_fields_); | 862 TransformToFastProperties(object_, unused_property_fields_); |
848 } | 863 } |
849 } | 864 } |
850 | 865 |
851 } } // namespace v8::internal | 866 } } // namespace v8::internal |
OLD | NEW |