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