| 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 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 result = enum_fun(info); | 541 result = enum_fun(info); |
| 542 } | 542 } |
| 543 } | 543 } |
| 544 return result; | 544 return result; |
| 545 } | 545 } |
| 546 | 546 |
| 547 | 547 |
| 548 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object, | 548 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object, |
| 549 KeyCollectionType type) { | 549 KeyCollectionType type) { |
| 550 Handle<FixedArray> content = Factory::empty_fixed_array(); | 550 Handle<FixedArray> content = Factory::empty_fixed_array(); |
| 551 Handle<JSObject> arguments_boilerplate = |
| 552 Handle<JSObject>( |
| 553 Top::context()->global_context()->arguments_boilerplate()); |
| 554 Handle<JSFunction> arguments_function = |
| 555 Handle<JSFunction>( |
| 556 JSFunction::cast(arguments_boilerplate->map()->constructor())); |
| 551 | 557 |
| 552 // Only collect keys if access is permitted. | 558 // Only collect keys if access is permitted. |
| 553 for (Handle<Object> p = object; | 559 for (Handle<Object> p = object; |
| 554 *p != Heap::null_value(); | 560 *p != Heap::null_value(); |
| 555 p = Handle<Object>(p->GetPrototype())) { | 561 p = Handle<Object>(p->GetPrototype())) { |
| 556 Handle<JSObject> current(JSObject::cast(*p)); | 562 Handle<JSObject> current(JSObject::cast(*p)); |
| 557 | 563 |
| 558 // Check access rights if required. | 564 // Check access rights if required. |
| 559 if (current->IsAccessCheckNeeded() && | 565 if (current->IsAccessCheckNeeded() && |
| 560 !Top::MayNamedAccess(*current, Heap::undefined_value(), | 566 !Top::MayNamedAccess(*current, Heap::undefined_value(), |
| 561 v8::ACCESS_KEYS)) { | 567 v8::ACCESS_KEYS)) { |
| 562 Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS); | 568 Top::ReportFailedAccessCheck(*current, v8::ACCESS_KEYS); |
| 563 break; | 569 break; |
| 564 } | 570 } |
| 565 | 571 |
| 566 // Compute the element keys. | 572 // Compute the element keys. |
| 567 Handle<FixedArray> element_keys = | 573 Handle<FixedArray> element_keys = |
| 568 Factory::NewFixedArray(current->NumberOfEnumElements()); | 574 Factory::NewFixedArray(current->NumberOfEnumElements()); |
| 569 current->GetEnumElementKeys(*element_keys); | 575 current->GetEnumElementKeys(*element_keys); |
| 570 content = UnionOfKeys(content, element_keys); | 576 content = UnionOfKeys(content, element_keys); |
| 571 | 577 |
| 572 // Add the element keys from the interceptor. | 578 // Add the element keys from the interceptor. |
| 573 if (current->HasIndexedInterceptor()) { | 579 if (current->HasIndexedInterceptor()) { |
| 574 v8::Handle<v8::Array> result = | 580 v8::Handle<v8::Array> result = |
| 575 GetKeysForIndexedInterceptor(object, current); | 581 GetKeysForIndexedInterceptor(object, current); |
| 576 if (!result.IsEmpty()) | 582 if (!result.IsEmpty()) |
| 577 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); | 583 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); |
| 578 } | 584 } |
| 579 | 585 |
| 580 // Compute the property keys. | 586 // We can cache the computed property keys if access checks are |
| 581 content = UnionOfKeys(content, GetEnumPropertyKeys(current)); | 587 // not needed and no interceptors are involved. |
| 588 // |
| 589 // We do not use the cache if the object has elements and |
| 590 // therefore it does not make sense to cache the property names |
| 591 // for arguments objects. Arguments objects will always have |
| 592 // elements. |
| 593 bool cache_enum_keys = |
| 594 ((current->map()->constructor() != *arguments_function) && |
| 595 !current->IsAccessCheckNeeded() && |
| 596 !current->HasNamedInterceptor() && |
| 597 !current->HasIndexedInterceptor()); |
| 598 // Compute the property keys and cache them if possible. |
| 599 content = |
| 600 UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys)); |
| 582 | 601 |
| 583 // Add the property keys from the interceptor. | 602 // Add the property keys from the interceptor. |
| 584 if (current->HasNamedInterceptor()) { | 603 if (current->HasNamedInterceptor()) { |
| 585 v8::Handle<v8::Array> result = | 604 v8::Handle<v8::Array> result = |
| 586 GetKeysForNamedInterceptor(object, current); | 605 GetKeysForNamedInterceptor(object, current); |
| 587 if (!result.IsEmpty()) | 606 if (!result.IsEmpty()) |
| 588 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); | 607 content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); |
| 589 } | 608 } |
| 590 | 609 |
| 591 // If we only want local properties we bail out after the first | 610 // If we only want local properties we bail out after the first |
| 592 // iteration. | 611 // iteration. |
| 593 if (type == LOCAL_ONLY) | 612 if (type == LOCAL_ONLY) |
| 594 break; | 613 break; |
| 595 } | 614 } |
| 596 return content; | 615 return content; |
| 597 } | 616 } |
| 598 | 617 |
| 599 | 618 |
| 600 Handle<JSArray> GetKeysFor(Handle<JSObject> object) { | 619 Handle<JSArray> GetKeysFor(Handle<JSObject> object) { |
| 601 Counters::for_in.Increment(); | 620 Counters::for_in.Increment(); |
| 602 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object, | 621 Handle<FixedArray> elements = GetKeysInFixedArrayFor(object, |
| 603 INCLUDE_PROTOS); | 622 INCLUDE_PROTOS); |
| 604 return Factory::NewJSArrayWithElements(elements); | 623 return Factory::NewJSArrayWithElements(elements); |
| 605 } | 624 } |
| 606 | 625 |
| 607 | 626 |
| 608 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object) { | 627 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, |
| 628 bool cache_result) { |
| 609 int index = 0; | 629 int index = 0; |
| 610 if (object->HasFastProperties()) { | 630 if (object->HasFastProperties()) { |
| 611 if (object->map()->instance_descriptors()->HasEnumCache()) { | 631 if (object->map()->instance_descriptors()->HasEnumCache()) { |
| 612 Counters::enum_cache_hits.Increment(); | 632 Counters::enum_cache_hits.Increment(); |
| 613 DescriptorArray* desc = object->map()->instance_descriptors(); | 633 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 614 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache())); | 634 return Handle<FixedArray>(FixedArray::cast(desc->GetEnumCache())); |
| 615 } | 635 } |
| 616 Counters::enum_cache_misses.Increment(); | 636 Counters::enum_cache_misses.Increment(); |
| 617 int num_enum = object->NumberOfEnumProperties(); | 637 int num_enum = object->NumberOfEnumProperties(); |
| 618 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum); | 638 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum); |
| 619 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum); | 639 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum); |
| 620 Handle<DescriptorArray> descs = | 640 Handle<DescriptorArray> descs = |
| 621 Handle<DescriptorArray>(object->map()->instance_descriptors()); | 641 Handle<DescriptorArray>(object->map()->instance_descriptors()); |
| 622 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 642 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 623 if (descs->IsProperty(i) && !descs->IsDontEnum(i)) { | 643 if (descs->IsProperty(i) && !descs->IsDontEnum(i)) { |
| 624 (*storage)->set(index, descs->GetKey(i)); | 644 (*storage)->set(index, descs->GetKey(i)); |
| 625 PropertyDetails details(descs->GetDetails(i)); | 645 PropertyDetails details(descs->GetDetails(i)); |
| 626 (*sort_array)->set(index, Smi::FromInt(details.index())); | 646 (*sort_array)->set(index, Smi::FromInt(details.index())); |
| 627 index++; | 647 index++; |
| 628 } | 648 } |
| 629 } | 649 } |
| 630 (*storage)->SortPairs(*sort_array, sort_array->length()); | 650 (*storage)->SortPairs(*sort_array, sort_array->length()); |
| 631 Handle<FixedArray> bridge_storage = | 651 if (cache_result) { |
| 632 Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength); | 652 Handle<FixedArray> bridge_storage = |
| 633 DescriptorArray* desc = object->map()->instance_descriptors(); | 653 Factory::NewFixedArray(DescriptorArray::kEnumCacheBridgeLength); |
| 634 desc->SetEnumCache(*bridge_storage, *storage); | 654 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 655 desc->SetEnumCache(*bridge_storage, *storage); |
| 656 } |
| 635 ASSERT(storage->length() == index); | 657 ASSERT(storage->length() == index); |
| 636 return storage; | 658 return storage; |
| 637 } else { | 659 } else { |
| 638 int num_enum = object->NumberOfEnumProperties(); | 660 int num_enum = object->NumberOfEnumProperties(); |
| 639 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum); | 661 Handle<FixedArray> storage = Factory::NewFixedArray(num_enum); |
| 640 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum); | 662 Handle<FixedArray> sort_array = Factory::NewFixedArray(num_enum); |
| 641 object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array); | 663 object->property_dictionary()->CopyEnumKeysTo(*storage, *sort_array); |
| 642 return storage; | 664 return storage; |
| 643 } | 665 } |
| 644 } | 666 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 Handle<Map> new_map = Factory::CopyMapDropTransitions(old_map); | 802 Handle<Map> new_map = Factory::CopyMapDropTransitions(old_map); |
| 781 obj->set_map(*new_map); | 803 obj->set_map(*new_map); |
| 782 new_map->set_needs_loading(true); | 804 new_map->set_needs_loading(true); |
| 783 // Store the lazy loading info in the constructor field. We'll | 805 // Store the lazy loading info in the constructor field. We'll |
| 784 // reestablish the constructor from the fixed array after loading. | 806 // reestablish the constructor from the fixed array after loading. |
| 785 new_map->set_constructor(*arr); | 807 new_map->set_constructor(*arr); |
| 786 ASSERT(!obj->IsLoaded()); | 808 ASSERT(!obj->IsLoaded()); |
| 787 } | 809 } |
| 788 | 810 |
| 789 } } // namespace v8::internal | 811 } } // namespace v8::internal |
| OLD | NEW |