| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 } | 448 } |
| 449 | 449 |
| 450 | 450 |
| 451 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, | 451 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, |
| 452 Handle<JSReceiver> receiver, | 452 Handle<JSReceiver> receiver, |
| 453 uint32_t index, | 453 uint32_t index, |
| 454 Handle<Object> value, | 454 Handle<Object> value, |
| 455 StrictModeFlag strict_mode) { | 455 StrictModeFlag strict_mode) { |
| 456 Isolate* isolate = proxy->GetIsolate(); | 456 Isolate* isolate = proxy->GetIsolate(); |
| 457 Handle<String> name = isolate->factory()->Uint32ToString(index); | 457 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 458 CALL_HEAP_FUNCTION(isolate, | 458 return SetPropertyWithHandler( |
| 459 proxy->SetPropertyWithHandler( | 459 proxy, receiver, name, value, NONE, strict_mode); |
| 460 *receiver, *name, *value, NONE, strict_mode), | |
| 461 Object); | |
| 462 } | 460 } |
| 463 | 461 |
| 464 | 462 |
| 465 bool JSProxy::HasElementWithHandler(uint32_t index) { | 463 bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) { |
| 466 String* name; | 464 Isolate* isolate = proxy->GetIsolate(); |
| 467 MaybeObject* maybe = GetHeap()->Uint32ToString(index); | 465 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 468 if (!maybe->To<String>(&name)) return maybe; | 466 return HasPropertyWithHandler(proxy, name); |
| 469 return HasPropertyWithHandler(name); | |
| 470 } | 467 } |
| 471 | 468 |
| 472 | 469 |
| 473 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, | 470 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, |
| 474 JSReceiver* getter) { | 471 JSReceiver* getter) { |
| 475 Isolate* isolate = getter->GetIsolate(); | 472 Isolate* isolate = getter->GetIsolate(); |
| 476 HandleScope scope(isolate); | 473 HandleScope scope(isolate); |
| 477 Handle<JSReceiver> fun(getter); | 474 Handle<JSReceiver> fun(getter); |
| 478 Handle<Object> self(receiver, isolate); | 475 Handle<Object> self(receiver, isolate); |
| 479 #ifdef ENABLE_DEBUGGER_SUPPORT | 476 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 ASSERT(!HasFastProperties()); | 633 ASSERT(!HasFastProperties()); |
| 637 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 634 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 638 if (IsGlobalObject()) { | 635 if (IsGlobalObject()) { |
| 639 value = PropertyCell::cast(value)->value(); | 636 value = PropertyCell::cast(value)->value(); |
| 640 } | 637 } |
| 641 ASSERT(!value->IsPropertyCell() && !value->IsCell()); | 638 ASSERT(!value->IsPropertyCell() && !value->IsCell()); |
| 642 return value; | 639 return value; |
| 643 } | 640 } |
| 644 | 641 |
| 645 | 642 |
| 646 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, | 643 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 647 LookupResult* result, | 644 LookupResult* result, |
| 648 Handle<Object> value) { | 645 Handle<Object> value) { |
| 649 CALL_HEAP_FUNCTION(object->GetIsolate(), | 646 ASSERT(!object->HasFastProperties()); |
| 650 object->SetNormalizedProperty(result, *value), | 647 NameDictionary* property_dictionary = object->property_dictionary(); |
| 651 Object); | 648 if (object->IsGlobalObject()) { |
| 649 Handle<PropertyCell> cell(PropertyCell::cast( |
| 650 property_dictionary->ValueAt(result->GetDictionaryEntry()))); |
| 651 PropertyCell::SetValueInferType(cell, value); |
| 652 } else { |
| 653 property_dictionary->ValueAtPut(result->GetDictionaryEntry(), *value); |
| 654 } |
| 652 } | 655 } |
| 653 | 656 |
| 654 | 657 |
| 655 MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result, | 658 // TODO(mstarzinger): Temporary wrapper until handlified. |
| 656 Object* value) { | 659 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, |
| 657 ASSERT(!HasFastProperties()); | 660 Handle<Name> name, |
| 658 if (IsGlobalObject()) { | 661 Handle<Object> value, |
| 659 PropertyCell* cell = PropertyCell::cast( | 662 PropertyDetails details) { |
| 660 property_dictionary()->ValueAt(result->GetDictionaryEntry())); | 663 CALL_HEAP_FUNCTION(dict->GetIsolate(), |
| 661 MaybeObject* maybe_type = cell->SetValueInferType(value); | 664 dict->Add(*name, *value, details), |
| 662 if (maybe_type->IsFailure()) return maybe_type; | 665 NameDictionary); |
| 663 } else { | |
| 664 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | |
| 665 } | |
| 666 return value; | |
| 667 } | 666 } |
| 668 | 667 |
| 669 | 668 |
| 670 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, | 669 void JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 671 Handle<Name> key, | 670 Handle<Name> name, |
| 672 Handle<Object> value, | 671 Handle<Object> value, |
| 673 PropertyDetails details) { | 672 PropertyDetails details) { |
| 674 CALL_HEAP_FUNCTION(object->GetIsolate(), | 673 ASSERT(!object->HasFastProperties()); |
| 675 object->SetNormalizedProperty(*key, *value, details), | 674 Handle<NameDictionary> property_dictionary(object->property_dictionary()); |
| 676 Object); | 675 int entry = property_dictionary->FindEntry(*name); |
| 677 } | |
| 678 | |
| 679 | |
| 680 MaybeObject* JSObject::SetNormalizedProperty(Name* name, | |
| 681 Object* value, | |
| 682 PropertyDetails details) { | |
| 683 ASSERT(!HasFastProperties()); | |
| 684 int entry = property_dictionary()->FindEntry(name); | |
| 685 if (entry == NameDictionary::kNotFound) { | 676 if (entry == NameDictionary::kNotFound) { |
| 686 Object* store_value = value; | 677 Handle<Object> store_value = value; |
| 687 if (IsGlobalObject()) { | 678 if (object->IsGlobalObject()) { |
| 688 Heap* heap = name->GetHeap(); | 679 store_value = object->GetIsolate()->factory()->NewPropertyCell(value); |
| 689 MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value); | |
| 690 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | |
| 691 } | 680 } |
| 692 Object* dict; | 681 property_dictionary = |
| 693 { MaybeObject* maybe_dict = | 682 NameDictionaryAdd(property_dictionary, name, store_value, details); |
| 694 property_dictionary()->Add(name, store_value, details); | 683 object->set_properties(*property_dictionary); |
| 695 if (!maybe_dict->ToObject(&dict)) return maybe_dict; | 684 return; |
| 696 } | |
| 697 set_properties(NameDictionary::cast(dict)); | |
| 698 return value; | |
| 699 } | 685 } |
| 700 | 686 |
| 701 PropertyDetails original_details = property_dictionary()->DetailsAt(entry); | 687 PropertyDetails original_details = property_dictionary->DetailsAt(entry); |
| 702 int enumeration_index; | 688 int enumeration_index; |
| 703 // Preserve the enumeration index unless the property was deleted. | 689 // Preserve the enumeration index unless the property was deleted. |
| 704 if (original_details.IsDeleted()) { | 690 if (original_details.IsDeleted()) { |
| 705 enumeration_index = property_dictionary()->NextEnumerationIndex(); | 691 enumeration_index = property_dictionary->NextEnumerationIndex(); |
| 706 property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1); | 692 property_dictionary->SetNextEnumerationIndex(enumeration_index + 1); |
| 707 } else { | 693 } else { |
| 708 enumeration_index = original_details.dictionary_index(); | 694 enumeration_index = original_details.dictionary_index(); |
| 709 ASSERT(enumeration_index > 0); | 695 ASSERT(enumeration_index > 0); |
| 710 } | 696 } |
| 711 | 697 |
| 712 details = PropertyDetails( | 698 details = PropertyDetails( |
| 713 details.attributes(), details.type(), enumeration_index); | 699 details.attributes(), details.type(), enumeration_index); |
| 714 | 700 |
| 715 if (IsGlobalObject()) { | 701 if (object->IsGlobalObject()) { |
| 716 PropertyCell* cell = | 702 Handle<PropertyCell> cell( |
| 717 PropertyCell::cast(property_dictionary()->ValueAt(entry)); | 703 PropertyCell::cast(property_dictionary->ValueAt(entry))); |
| 718 MaybeObject* maybe_type = cell->SetValueInferType(value); | 704 PropertyCell::SetValueInferType(cell, value); |
| 719 if (maybe_type->IsFailure()) return maybe_type; | |
| 720 // Please note we have to update the property details. | 705 // Please note we have to update the property details. |
| 721 property_dictionary()->DetailsAtPut(entry, details); | 706 property_dictionary->DetailsAtPut(entry, details); |
| 722 } else { | 707 } else { |
| 723 property_dictionary()->SetEntry(entry, name, value, details); | 708 property_dictionary->SetEntry(entry, *name, *value, details); |
| 724 } | 709 } |
| 725 return value; | |
| 726 } | 710 } |
| 727 | 711 |
| 728 | 712 |
| 729 // TODO(mstarzinger): Temporary wrapper until target is handlified. | 713 // TODO(mstarzinger): Temporary wrapper until target is handlified. |
| 730 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict, | 714 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict, |
| 731 Handle<Name> name) { | 715 Handle<Name> name) { |
| 732 CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary); | 716 CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary); |
| 733 } | 717 } |
| 734 | 718 |
| 735 | 719 |
| 736 static void CellSetValueInferType(Handle<PropertyCell> cell, | |
| 737 Handle<Object> value) { | |
| 738 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), cell->SetValueInferType(*value)); | |
| 739 } | |
| 740 | |
| 741 | |
| 742 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 720 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object, |
| 743 Handle<Name> name, | 721 Handle<Name> name, |
| 744 DeleteMode mode) { | 722 DeleteMode mode) { |
| 745 ASSERT(!object->HasFastProperties()); | 723 ASSERT(!object->HasFastProperties()); |
| 746 Isolate* isolate = object->GetIsolate(); | 724 Isolate* isolate = object->GetIsolate(); |
| 747 Handle<NameDictionary> dictionary(object->property_dictionary()); | 725 Handle<NameDictionary> dictionary(object->property_dictionary()); |
| 748 int entry = dictionary->FindEntry(*name); | 726 int entry = dictionary->FindEntry(*name); |
| 749 if (entry != NameDictionary::kNotFound) { | 727 if (entry != NameDictionary::kNotFound) { |
| 750 // If we have a global object set the cell to the hole. | 728 // If we have a global object set the cell to the hole. |
| 751 if (object->IsGlobalObject()) { | 729 if (object->IsGlobalObject()) { |
| 752 PropertyDetails details = dictionary->DetailsAt(entry); | 730 PropertyDetails details = dictionary->DetailsAt(entry); |
| 753 if (details.IsDontDelete()) { | 731 if (details.IsDontDelete()) { |
| 754 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); | 732 if (mode != FORCE_DELETION) return isolate->factory()->false_value(); |
| 755 // When forced to delete global properties, we have to make a | 733 // When forced to delete global properties, we have to make a |
| 756 // map change to invalidate any ICs that think they can load | 734 // map change to invalidate any ICs that think they can load |
| 757 // from the DontDelete cell without checking if it contains | 735 // from the DontDelete cell without checking if it contains |
| 758 // the hole value. | 736 // the hole value. |
| 759 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); | 737 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 760 ASSERT(new_map->is_dictionary_map()); | 738 ASSERT(new_map->is_dictionary_map()); |
| 761 object->set_map(*new_map); | 739 object->set_map(*new_map); |
| 762 } | 740 } |
| 763 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); | 741 Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry))); |
| 764 CellSetValueInferType(cell, isolate->factory()->the_hole_value()); | 742 Handle<Object> value = isolate->factory()->the_hole_value(); |
| 743 PropertyCell::SetValueInferType(cell, value); |
| 765 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 744 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 766 } else { | 745 } else { |
| 767 Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate); | 746 Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate); |
| 768 if (*deleted == isolate->heap()->true_value()) { | 747 if (*deleted == isolate->heap()->true_value()) { |
| 769 Handle<NameDictionary> new_properties = | 748 Handle<NameDictionary> new_properties = |
| 770 NameDictionaryShrink(dictionary, name); | 749 NameDictionaryShrink(dictionary, name); |
| 771 object->set_properties(*new_properties); | 750 object->set_properties(*new_properties); |
| 772 } | 751 } |
| 773 return deleted; | 752 return deleted; |
| 774 } | 753 } |
| (...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1864 // If the constructor is not present, return "Object". | 1843 // If the constructor is not present, return "Object". |
| 1865 return GetHeap()->Object_string(); | 1844 return GetHeap()->Object_string(); |
| 1866 } | 1845 } |
| 1867 | 1846 |
| 1868 | 1847 |
| 1869 String* JSReceiver::constructor_name() { | 1848 String* JSReceiver::constructor_name() { |
| 1870 return map()->constructor_name(); | 1849 return map()->constructor_name(); |
| 1871 } | 1850 } |
| 1872 | 1851 |
| 1873 | 1852 |
| 1874 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, | 1853 // TODO(mstarzinger): Temporary wrapper until handlified. |
| 1875 Name* name, | 1854 static Handle<Object> NewStorageFor(Isolate* isolate, |
| 1876 Object* value, | 1855 Handle<Object> object, |
| 1877 int field_index, | 1856 Representation representation) { |
| 1878 Representation representation) { | 1857 Heap* heap = isolate->heap(); |
| 1858 CALL_HEAP_FUNCTION(isolate, |
| 1859 object->AllocateNewStorageFor(heap, representation), |
| 1860 Object); |
| 1861 } |
| 1862 |
| 1863 |
| 1864 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object, |
| 1865 Handle<Map> new_map, |
| 1866 Handle<Name> name, |
| 1867 Handle<Object> value, |
| 1868 int field_index, |
| 1869 Representation representation) { |
| 1870 Isolate* isolate = object->GetIsolate(); |
| 1871 |
| 1879 // This method is used to transition to a field. If we are transitioning to a | 1872 // This method is used to transition to a field. If we are transitioning to a |
| 1880 // double field, allocate new storage. | 1873 // double field, allocate new storage. |
| 1881 Object* storage; | 1874 Handle<Object> storage = NewStorageFor(isolate, value, representation); |
| 1882 MaybeObject* maybe_storage = | 1875 |
| 1883 value->AllocateNewStorageFor(GetHeap(), representation); | 1876 if (object->map()->unused_property_fields() == 0) { |
| 1884 if (!maybe_storage->To(&storage)) return maybe_storage; | |
| 1885 | |
| 1886 if (map()->unused_property_fields() == 0) { | |
| 1887 int new_unused = new_map->unused_property_fields(); | 1877 int new_unused = new_map->unused_property_fields(); |
| 1888 FixedArray* values; | 1878 Handle<FixedArray> properties(object->properties()); |
| 1889 MaybeObject* maybe_values = | 1879 Handle<FixedArray> values = isolate->factory()->CopySizeFixedArray( |
| 1890 properties()->CopySize(properties()->length() + new_unused + 1); | 1880 properties, properties->length() + new_unused + 1); |
| 1891 if (!maybe_values->To(&values)) return maybe_values; | 1881 object->set_properties(*values); |
| 1892 | 1882 } |
| 1893 set_properties(values); | 1883 |
| 1894 } | 1884 object->set_map(*new_map); |
| 1895 | 1885 object->FastPropertyAtPut(field_index, *storage); |
| 1896 set_map(new_map); | 1886 } |
| 1897 | 1887 |
| 1898 FastPropertyAtPut(field_index, storage); | 1888 |
| 1899 return value; | 1889 static MaybeObject* CopyAddFieldDescriptor(Map* map, |
| 1900 } | 1890 Name* name, |
| 1901 | 1891 int index, |
| 1902 | 1892 PropertyAttributes attributes, |
| 1903 MaybeObject* JSObject::AddFastProperty(Name* name, | 1893 Representation representation, |
| 1904 Object* value, | 1894 TransitionFlag flag) { |
| 1905 PropertyAttributes attributes, | 1895 Map* new_map; |
| 1906 StoreFromKeyed store_mode, | 1896 FieldDescriptor new_field_desc(name, index, attributes, representation); |
| 1907 ValueType value_type, | 1897 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); |
| 1908 TransitionFlag flag) { | 1898 if (!maybe_map->To(&new_map)) return maybe_map; |
| 1909 ASSERT(!IsJSGlobalProxy()); | 1899 int unused_property_fields = map->unused_property_fields() - 1; |
| 1900 if (unused_property_fields < 0) { |
| 1901 unused_property_fields += JSObject::kFieldsAdded; |
| 1902 } |
| 1903 new_map->set_unused_property_fields(unused_property_fields); |
| 1904 return new_map; |
| 1905 } |
| 1906 |
| 1907 |
| 1908 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, |
| 1909 Handle<Name> name, |
| 1910 int index, |
| 1911 PropertyAttributes attributes, |
| 1912 Representation representation, |
| 1913 TransitionFlag flag) { |
| 1914 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 1915 CopyAddFieldDescriptor( |
| 1916 *map, *name, index, attributes, representation, flag), |
| 1917 Map); |
| 1918 } |
| 1919 |
| 1920 |
| 1921 void JSObject::AddFastProperty(Handle<JSObject> object, |
| 1922 Handle<Name> name, |
| 1923 Handle<Object> value, |
| 1924 PropertyAttributes attributes, |
| 1925 StoreFromKeyed store_mode, |
| 1926 ValueType value_type, |
| 1927 TransitionFlag flag) { |
| 1928 ASSERT(!object->IsJSGlobalProxy()); |
| 1910 ASSERT(DescriptorArray::kNotFound == | 1929 ASSERT(DescriptorArray::kNotFound == |
| 1911 map()->instance_descriptors()->Search( | 1930 object->map()->instance_descriptors()->Search( |
| 1912 name, map()->NumberOfOwnDescriptors())); | 1931 *name, object->map()->NumberOfOwnDescriptors())); |
| 1913 | 1932 |
| 1914 // Normalize the object if the name is an actual name (not the | 1933 // Normalize the object if the name is an actual name (not the |
| 1915 // hidden strings) and is not a real identifier. | 1934 // hidden strings) and is not a real identifier. |
| 1916 // Normalize the object if it will have too many fast properties. | 1935 // Normalize the object if it will have too many fast properties. |
| 1917 Isolate* isolate = GetHeap()->isolate(); | 1936 Isolate* isolate = object->GetIsolate(); |
| 1918 if (!name->IsCacheable(isolate) || TooManyFastProperties(store_mode)) { | 1937 if (!name->IsCacheable(isolate) || |
| 1919 MaybeObject* maybe_failure = | 1938 object->TooManyFastProperties(store_mode)) { |
| 1920 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1939 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 1921 if (maybe_failure->IsFailure()) return maybe_failure; | 1940 AddSlowProperty(object, name, value, attributes); |
| 1922 return AddSlowProperty(name, value, attributes); | 1941 return; |
| 1923 } | 1942 } |
| 1924 | 1943 |
| 1925 // Compute the new index for new field. | 1944 // Compute the new index for new field. |
| 1926 int index = map()->NextFreePropertyIndex(); | 1945 int index = object->map()->NextFreePropertyIndex(); |
| 1927 | 1946 |
| 1928 // Allocate new instance descriptors with (name, index) added | 1947 // Allocate new instance descriptors with (name, index) added |
| 1929 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 1948 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
| 1930 Representation representation = value->OptimalRepresentation(value_type); | 1949 Representation representation = value->OptimalRepresentation(value_type); |
| 1931 | 1950 Handle<Map> new_map = CopyAddFieldDescriptor( |
| 1932 FieldDescriptor new_field(name, index, attributes, representation); | 1951 handle(object->map()), name, index, attributes, representation, flag); |
| 1933 | 1952 |
| 1934 Map* new_map; | 1953 AddFastPropertyUsingMap(object, new_map, name, value, index, representation); |
| 1935 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag); | 1954 } |
| 1936 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 1955 |
| 1937 | 1956 |
| 1938 int unused_property_fields = map()->unused_property_fields() - 1; | 1957 static MaybeObject* CopyAddConstantDescriptor(Map* map, |
| 1939 if (unused_property_fields < 0) { | 1958 Name* name, |
| 1940 unused_property_fields += kFieldsAdded; | 1959 Object* value, |
| 1941 } | 1960 PropertyAttributes attributes, |
| 1942 new_map->set_unused_property_fields(unused_property_fields); | 1961 TransitionFlag flag) { |
| 1943 | 1962 ConstantDescriptor new_constant_desc(name, value, attributes); |
| 1944 return AddFastPropertyUsingMap(new_map, name, value, index, representation); | 1963 return map->CopyAddDescriptor(&new_constant_desc, flag); |
| 1945 } | 1964 } |
| 1946 | 1965 |
| 1947 | 1966 |
| 1948 MaybeObject* JSObject::AddConstantProperty( | 1967 static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map, |
| 1949 Name* name, | 1968 Handle<Name> name, |
| 1950 Object* constant, | 1969 Handle<Object> value, |
| 1951 PropertyAttributes attributes, | 1970 PropertyAttributes attributes, |
| 1952 TransitionFlag initial_flag) { | 1971 TransitionFlag flag) { |
| 1953 // Allocate new instance descriptors with (name, constant) added | 1972 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 1954 ConstantDescriptor d(name, constant, attributes); | 1973 CopyAddConstantDescriptor( |
| 1955 | 1974 *map, *name, *value, attributes, flag), |
| 1975 Map); |
| 1976 } |
| 1977 |
| 1978 |
| 1979 void JSObject::AddConstantProperty(Handle<JSObject> object, |
| 1980 Handle<Name> name, |
| 1981 Handle<Object> constant, |
| 1982 PropertyAttributes attributes, |
| 1983 TransitionFlag initial_flag) { |
| 1956 TransitionFlag flag = | 1984 TransitionFlag flag = |
| 1957 // Do not add transitions to global objects. | 1985 // Do not add transitions to global objects. |
| 1958 (IsGlobalObject() || | 1986 (object->IsGlobalObject() || |
| 1959 // Don't add transitions to special properties with non-trivial | 1987 // Don't add transitions to special properties with non-trivial |
| 1960 // attributes. | 1988 // attributes. |
| 1961 attributes != NONE) | 1989 attributes != NONE) |
| 1962 ? OMIT_TRANSITION | 1990 ? OMIT_TRANSITION |
| 1963 : initial_flag; | 1991 : initial_flag; |
| 1964 | 1992 |
| 1965 Map* new_map; | 1993 // Allocate new instance descriptors with (name, constant) added. |
| 1966 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); | 1994 Handle<Map> new_map = CopyAddConstantDescriptor( |
| 1967 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 1995 handle(object->map()), name, constant, attributes, flag); |
| 1968 | 1996 |
| 1969 set_map(new_map); | 1997 object->set_map(*new_map); |
| 1970 return constant; | 1998 } |
| 1971 } | 1999 |
| 1972 | 2000 |
| 1973 | 2001 void JSObject::AddSlowProperty(Handle<JSObject> object, |
| 1974 // Add property in slow mode | 2002 Handle<Name> name, |
| 1975 MaybeObject* JSObject::AddSlowProperty(Name* name, | 2003 Handle<Object> value, |
| 1976 Object* value, | 2004 PropertyAttributes attributes) { |
| 1977 PropertyAttributes attributes) { | 2005 ASSERT(!object->HasFastProperties()); |
| 1978 ASSERT(!HasFastProperties()); | 2006 Isolate* isolate = object->GetIsolate(); |
| 1979 NameDictionary* dict = property_dictionary(); | 2007 Handle<NameDictionary> dict(object->property_dictionary()); |
| 1980 Object* store_value = value; | 2008 if (object->IsGlobalObject()) { |
| 1981 if (IsGlobalObject()) { | |
| 1982 // In case name is an orphaned property reuse the cell. | 2009 // In case name is an orphaned property reuse the cell. |
| 1983 int entry = dict->FindEntry(name); | 2010 int entry = dict->FindEntry(*name); |
| 1984 if (entry != NameDictionary::kNotFound) { | 2011 if (entry != NameDictionary::kNotFound) { |
| 1985 store_value = dict->ValueAt(entry); | 2012 Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry))); |
| 1986 MaybeObject* maybe_type = | 2013 PropertyCell::SetValueInferType(cell, value); |
| 1987 PropertyCell::cast(store_value)->SetValueInferType(value); | |
| 1988 if (maybe_type->IsFailure()) return maybe_type; | |
| 1989 // Assign an enumeration index to the property and update | 2014 // Assign an enumeration index to the property and update |
| 1990 // SetNextEnumerationIndex. | 2015 // SetNextEnumerationIndex. |
| 1991 int index = dict->NextEnumerationIndex(); | 2016 int index = dict->NextEnumerationIndex(); |
| 1992 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); | 2017 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
| 1993 dict->SetNextEnumerationIndex(index + 1); | 2018 dict->SetNextEnumerationIndex(index + 1); |
| 1994 dict->SetEntry(entry, name, store_value, details); | 2019 dict->SetEntry(entry, *name, *cell, details); |
| 1995 return value; | 2020 return; |
| 1996 } | 2021 } |
| 1997 Heap* heap = GetHeap(); | 2022 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value); |
| 1998 { MaybeObject* maybe_store_value = | 2023 PropertyCell::SetValueInferType(cell, value); |
| 1999 heap->AllocatePropertyCell(value); | 2024 value = cell; |
| 2000 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | |
| 2001 } | |
| 2002 MaybeObject* maybe_type = | |
| 2003 PropertyCell::cast(store_value)->SetValueInferType(value); | |
| 2004 if (maybe_type->IsFailure()) return maybe_type; | |
| 2005 } | 2025 } |
| 2006 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 2026 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
| 2007 Object* result; | 2027 Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details); |
| 2008 { MaybeObject* maybe_result = dict->Add(name, store_value, details); | 2028 if (*dict != *result) object->set_properties(*result); |
| 2009 if (!maybe_result->ToObject(&result)) return maybe_result; | 2029 } |
| 2010 } | 2030 |
| 2011 if (dict != result) set_properties(NameDictionary::cast(result)); | 2031 |
| 2012 return value; | 2032 Handle<Object> JSObject::AddProperty(Handle<JSObject> object, |
| 2013 } | 2033 Handle<Name> name, |
| 2014 | 2034 Handle<Object> value, |
| 2015 | 2035 PropertyAttributes attributes, |
| 2016 MaybeObject* JSObject::AddProperty(Name* name, | 2036 StrictModeFlag strict_mode, |
| 2017 Object* value, | 2037 JSReceiver::StoreFromKeyed store_mode, |
| 2018 PropertyAttributes attributes, | 2038 ExtensibilityCheck extensibility_check, |
| 2019 StrictModeFlag strict_mode, | 2039 ValueType value_type, |
| 2020 JSReceiver::StoreFromKeyed store_mode, | 2040 StoreMode mode, |
| 2021 ExtensibilityCheck extensibility_check, | 2041 TransitionFlag transition_flag) { |
| 2022 ValueType value_type, | 2042 ASSERT(!object->IsJSGlobalProxy()); |
| 2023 StoreMode mode, | 2043 Isolate* isolate = object->GetIsolate(); |
| 2024 TransitionFlag transition_flag) { | |
| 2025 ASSERT(!IsJSGlobalProxy()); | |
| 2026 Map* map_of_this = map(); | |
| 2027 Heap* heap = GetHeap(); | |
| 2028 Isolate* isolate = heap->isolate(); | |
| 2029 MaybeObject* result; | |
| 2030 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2044 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
| 2031 !map_of_this->is_extensible()) { | 2045 !object->map()->is_extensible()) { |
| 2032 if (strict_mode == kNonStrictMode) { | 2046 if (strict_mode == kNonStrictMode) { |
| 2033 return value; | 2047 return value; |
| 2034 } else { | 2048 } else { |
| 2035 Handle<Object> args[1] = {Handle<Name>(name)}; | 2049 Handle<Object> args[1] = { name }; |
| 2036 return isolate->Throw( | 2050 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2037 *isolate->factory()->NewTypeError("object_not_extensible", | 2051 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
| 2038 HandleVector(args, 1))); | 2052 isolate->Throw(*error); |
| 2053 return Handle<Object>(); |
| 2039 } | 2054 } |
| 2040 } | 2055 } |
| 2041 | 2056 |
| 2042 if (HasFastProperties()) { | 2057 if (object->HasFastProperties()) { |
| 2043 // Ensure the descriptor array does not get too big. | 2058 // Ensure the descriptor array does not get too big. |
| 2044 if (map_of_this->NumberOfOwnDescriptors() < | 2059 if (object->map()->NumberOfOwnDescriptors() < |
| 2045 DescriptorArray::kMaxNumberOfDescriptors) { | 2060 DescriptorArray::kMaxNumberOfDescriptors) { |
| 2046 // TODO(verwaest): Support other constants. | 2061 // TODO(verwaest): Support other constants. |
| 2047 // if (mode == ALLOW_AS_CONSTANT && | 2062 // if (mode == ALLOW_AS_CONSTANT && |
| 2048 // !value->IsTheHole() && | 2063 // !value->IsTheHole() && |
| 2049 // !value->IsConsString()) { | 2064 // !value->IsConsString()) { |
| 2050 if (value->IsJSFunction()) { | 2065 if (value->IsJSFunction()) { |
| 2051 result = AddConstantProperty(name, value, attributes, transition_flag); | 2066 AddConstantProperty(object, name, value, attributes, transition_flag); |
| 2052 } else { | 2067 } else { |
| 2053 result = AddFastProperty( | 2068 AddFastProperty(object, name, value, attributes, store_mode, |
| 2054 name, value, attributes, store_mode, value_type, transition_flag); | 2069 value_type, transition_flag); |
| 2055 } | 2070 } |
| 2056 } else { | 2071 } else { |
| 2057 // Normalize the object to prevent very large instance descriptors. | 2072 // Normalize the object to prevent very large instance descriptors. |
| 2058 // This eliminates unwanted N^2 allocation and lookup behavior. | 2073 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2059 Object* obj; | 2074 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 2060 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2075 AddSlowProperty(object, name, value, attributes); |
| 2061 if (!maybe->To(&obj)) return maybe; | |
| 2062 result = AddSlowProperty(name, value, attributes); | |
| 2063 } | 2076 } |
| 2064 } else { | 2077 } else { |
| 2065 result = AddSlowProperty(name, value, attributes); | 2078 AddSlowProperty(object, name, value, attributes); |
| 2066 } | 2079 } |
| 2067 | 2080 |
| 2068 Handle<Object> hresult; | 2081 if (FLAG_harmony_observation && object->map()->is_observed()) { |
| 2069 if (!result->ToHandle(&hresult, isolate)) return result; | 2082 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 2070 | 2083 EnqueueChangeRecord(object, "new", name, old_value); |
| 2071 if (FLAG_harmony_observation && map()->is_observed()) { | 2084 } |
| 2072 EnqueueChangeRecord(handle(this, isolate), | 2085 |
| 2073 "new", | 2086 return value; |
| 2074 handle(name, isolate), | 2087 } |
| 2075 handle(heap->the_hole_value(), isolate)); | 2088 |
| 2076 } | 2089 |
| 2077 | |
| 2078 return *hresult; | |
| 2079 } | |
| 2080 | |
| 2081 | |
| 2082 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2090 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| 2083 const char* type_str, | 2091 const char* type_str, |
| 2084 Handle<Name> name, | 2092 Handle<Name> name, |
| 2085 Handle<Object> old_value) { | 2093 Handle<Object> old_value) { |
| 2086 Isolate* isolate = object->GetIsolate(); | 2094 Isolate* isolate = object->GetIsolate(); |
| 2087 HandleScope scope(isolate); | 2095 HandleScope scope(isolate); |
| 2088 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); | 2096 Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str); |
| 2089 if (object->IsJSGlobalObject()) { | 2097 if (object->IsJSGlobalObject()) { |
| 2090 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); | 2098 object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate); |
| 2091 } | 2099 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2108 isolate->observers_deliver_changes(), | 2116 isolate->observers_deliver_changes(), |
| 2109 isolate->factory()->undefined_value(), | 2117 isolate->factory()->undefined_value(), |
| 2110 0, | 2118 0, |
| 2111 NULL, | 2119 NULL, |
| 2112 &threw); | 2120 &threw); |
| 2113 ASSERT(!threw); | 2121 ASSERT(!threw); |
| 2114 isolate->set_observer_delivery_pending(false); | 2122 isolate->set_observer_delivery_pending(false); |
| 2115 } | 2123 } |
| 2116 | 2124 |
| 2117 | 2125 |
| 2118 MaybeObject* JSObject::SetPropertyPostInterceptor( | 2126 Handle<Object> JSObject::SetPropertyPostInterceptor( |
| 2119 Name* name, | 2127 Handle<JSObject> object, |
| 2120 Object* value, | 2128 Handle<Name> name, |
| 2129 Handle<Object> value, |
| 2121 PropertyAttributes attributes, | 2130 PropertyAttributes attributes, |
| 2122 StrictModeFlag strict_mode, | 2131 StrictModeFlag strict_mode) { |
| 2123 StoreMode mode) { | |
| 2124 // Check local property, ignore interceptor. | 2132 // Check local property, ignore interceptor. |
| 2125 LookupResult result(GetIsolate()); | 2133 LookupResult result(object->GetIsolate()); |
| 2126 LocalLookupRealNamedProperty(name, &result); | 2134 object->LocalLookupRealNamedProperty(*name, &result); |
| 2127 if (!result.IsFound()) map()->LookupTransition(this, name, &result); | 2135 if (!result.IsFound()) { |
| 2136 object->map()->LookupTransition(*object, *name, &result); |
| 2137 } |
| 2128 if (result.IsFound()) { | 2138 if (result.IsFound()) { |
| 2129 // An existing property or a map transition was found. Use set property to | 2139 // An existing property or a map transition was found. Use set property to |
| 2130 // handle all these cases. | 2140 // handle all these cases. |
| 2131 return SetProperty(&result, name, value, attributes, strict_mode); | 2141 return SetPropertyForResult(object, &result, name, value, attributes, |
| 2142 strict_mode, MAY_BE_STORE_FROM_KEYED); |
| 2132 } | 2143 } |
| 2133 bool done = false; | 2144 bool done = false; |
| 2134 MaybeObject* result_object = | 2145 Handle<Object> result_object = SetPropertyViaPrototypes( |
| 2135 SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); | 2146 object, name, value, attributes, strict_mode, &done); |
| 2136 if (done) return result_object; | 2147 if (done) return result_object; |
| 2137 // Add a new real property. | 2148 // Add a new real property. |
| 2138 return AddProperty(name, value, attributes, strict_mode, | 2149 return AddProperty(object, name, value, attributes, strict_mode); |
| 2139 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, | |
| 2140 OPTIMAL_REPRESENTATION, mode); | |
| 2141 } | 2150 } |
| 2142 | 2151 |
| 2143 | 2152 |
| 2144 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, | 2153 static void ReplaceSlowProperty(Handle<JSObject> object, |
| 2145 Object* value, | 2154 Handle<Name> name, |
| 2146 PropertyAttributes attributes) { | 2155 Handle<Object> value, |
| 2147 NameDictionary* dictionary = property_dictionary(); | 2156 PropertyAttributes attributes) { |
| 2148 int old_index = dictionary->FindEntry(name); | 2157 NameDictionary* dictionary = object->property_dictionary(); |
| 2158 int old_index = dictionary->FindEntry(*name); |
| 2149 int new_enumeration_index = 0; // 0 means "Use the next available index." | 2159 int new_enumeration_index = 0; // 0 means "Use the next available index." |
| 2150 if (old_index != -1) { | 2160 if (old_index != -1) { |
| 2151 // All calls to ReplaceSlowProperty have had all transitions removed. | 2161 // All calls to ReplaceSlowProperty have had all transitions removed. |
| 2152 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2162 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
| 2153 } | 2163 } |
| 2154 | 2164 |
| 2155 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2165 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
| 2156 return SetNormalizedProperty(name, value, new_details); | 2166 JSObject::SetNormalizedProperty(object, name, value, new_details); |
| 2157 } | 2167 } |
| 2158 | 2168 |
| 2159 | 2169 |
| 2160 const char* Representation::Mnemonic() const { | 2170 const char* Representation::Mnemonic() const { |
| 2161 switch (kind_) { | 2171 switch (kind_) { |
| 2162 case kNone: return "v"; | 2172 case kNone: return "v"; |
| 2163 case kTagged: return "t"; | 2173 case kTagged: return "t"; |
| 2164 case kSmi: return "s"; | 2174 case kSmi: return "s"; |
| 2165 case kDouble: return "d"; | 2175 case kDouble: return "d"; |
| 2166 case kInteger32: return "i"; | 2176 case kInteger32: return "i"; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2253 ASSERT(target_inobject < inobject_properties()); | 2263 ASSERT(target_inobject < inobject_properties()); |
| 2254 if (target_number_of_fields <= target_inobject) { | 2264 if (target_number_of_fields <= target_inobject) { |
| 2255 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2265 ASSERT(target_number_of_fields + target_unused == target_inobject); |
| 2256 return false; | 2266 return false; |
| 2257 } | 2267 } |
| 2258 // Otherwise, properties will need to be moved to the backing store. | 2268 // Otherwise, properties will need to be moved to the backing store. |
| 2259 return true; | 2269 return true; |
| 2260 } | 2270 } |
| 2261 | 2271 |
| 2262 | 2272 |
| 2273 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { |
| 2274 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map)); |
| 2275 } |
| 2276 |
| 2277 |
| 2263 // To migrate an instance to a map: | 2278 // To migrate an instance to a map: |
| 2264 // - First check whether the instance needs to be rewritten. If not, simply | 2279 // - First check whether the instance needs to be rewritten. If not, simply |
| 2265 // change the map. | 2280 // change the map. |
| 2266 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2281 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
| 2267 // addition to unused space. | 2282 // addition to unused space. |
| 2268 // - Copy all existing properties in, in the following order: backing store | 2283 // - Copy all existing properties in, in the following order: backing store |
| 2269 // properties, unused fields, inobject properties. | 2284 // properties, unused fields, inobject properties. |
| 2270 // - If all allocation succeeded, commit the state atomically: | 2285 // - If all allocation succeeded, commit the state atomically: |
| 2271 // * Copy inobject properties from the backing store back into the object. | 2286 // * Copy inobject properties from the backing store back into the object. |
| 2272 // * Trim the difference in instance size of the object. This also cleanly | 2287 // * Trim the difference in instance size of the object. This also cleanly |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2354 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); | 2369 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); |
| 2355 set_properties(array); | 2370 set_properties(array); |
| 2356 } | 2371 } |
| 2357 | 2372 |
| 2358 set_map(new_map); | 2373 set_map(new_map); |
| 2359 | 2374 |
| 2360 return this; | 2375 return this; |
| 2361 } | 2376 } |
| 2362 | 2377 |
| 2363 | 2378 |
| 2364 MaybeObject* JSObject::GeneralizeFieldRepresentation( | 2379 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
| 2365 int modify_index, | 2380 int modify_index, |
| 2366 Representation new_representation, | 2381 Representation new_representation, |
| 2367 StoreMode store_mode) { | 2382 StoreMode store_mode) { |
| 2368 Map* new_map; | 2383 Handle<Map> new_map = Map::GeneralizeRepresentation( |
| 2369 MaybeObject* maybe_new_map = map()->GeneralizeRepresentation( | 2384 handle(object->map()), modify_index, new_representation, store_mode); |
| 2370 modify_index, new_representation, store_mode); | 2385 if (object->map() == *new_map) return; |
| 2371 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2386 return MigrateToMap(object, new_map); |
| 2372 if (map() == new_map) return this; | |
| 2373 | |
| 2374 return MigrateToMap(new_map); | |
| 2375 } | 2387 } |
| 2376 | 2388 |
| 2377 | 2389 |
| 2378 int Map::NumberOfFields() { | 2390 int Map::NumberOfFields() { |
| 2379 DescriptorArray* descriptors = instance_descriptors(); | 2391 DescriptorArray* descriptors = instance_descriptors(); |
| 2380 int result = 0; | 2392 int result = 0; |
| 2381 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2393 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
| 2382 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2394 if (descriptors->GetDetails(i).type() == FIELD) result++; |
| 2383 } | 2395 } |
| 2384 return result; | 2396 return result; |
| 2385 } | 2397 } |
| 2386 | 2398 |
| 2387 | 2399 |
| 2388 MaybeObject* Map::CopyGeneralizeAllRepresentations( | 2400 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
| 2389 int modify_index, | 2401 int modify_index, |
| 2390 StoreMode store_mode, | 2402 StoreMode store_mode, |
| 2391 PropertyAttributes attributes, | 2403 PropertyAttributes attributes, |
| 2392 const char* reason) { | 2404 const char* reason) { |
| 2393 Map* new_map; | 2405 Handle<Map> new_map = Copy(map); |
| 2394 MaybeObject* maybe_map = this->Copy(); | |
| 2395 if (!maybe_map->To(&new_map)) return maybe_map; | |
| 2396 | 2406 |
| 2397 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2407 DescriptorArray* descriptors = new_map->instance_descriptors(); |
| 2398 descriptors->InitializeRepresentations(Representation::Tagged()); | 2408 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 2399 | 2409 |
| 2400 // Unless the instance is being migrated, ensure that modify_index is a field. | 2410 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2401 PropertyDetails details = descriptors->GetDetails(modify_index); | 2411 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2402 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2412 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
| 2403 FieldDescriptor d(descriptors->GetKey(modify_index), | 2413 FieldDescriptor d(descriptors->GetKey(modify_index), |
| 2404 new_map->NumberOfFields(), | 2414 new_map->NumberOfFields(), |
| 2405 attributes, | 2415 attributes, |
| 2406 Representation::Tagged()); | 2416 Representation::Tagged()); |
| 2407 d.SetSortedKeyIndex(details.pointer()); | 2417 d.SetSortedKeyIndex(details.pointer()); |
| 2408 descriptors->Set(modify_index, &d); | 2418 descriptors->Set(modify_index, &d); |
| 2409 int unused_property_fields = new_map->unused_property_fields() - 1; | 2419 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2410 if (unused_property_fields < 0) { | 2420 if (unused_property_fields < 0) { |
| 2411 unused_property_fields += JSObject::kFieldsAdded; | 2421 unused_property_fields += JSObject::kFieldsAdded; |
| 2412 } | 2422 } |
| 2413 new_map->set_unused_property_fields(unused_property_fields); | 2423 new_map->set_unused_property_fields(unused_property_fields); |
| 2414 } | 2424 } |
| 2415 | 2425 |
| 2416 if (FLAG_trace_generalization) { | 2426 if (FLAG_trace_generalization) { |
| 2417 PrintGeneralization(stdout, reason, modify_index, | 2427 map->PrintGeneralization(stdout, reason, modify_index, |
| 2418 new_map->NumberOfOwnDescriptors(), | 2428 new_map->NumberOfOwnDescriptors(), |
| 2419 new_map->NumberOfOwnDescriptors(), | 2429 new_map->NumberOfOwnDescriptors(), |
| 2420 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2430 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| 2421 Representation::Tagged(), Representation::Tagged()); | 2431 Representation::Tagged(), Representation::Tagged()); |
| 2422 } | 2432 } |
| 2423 return new_map; | 2433 return new_map; |
| 2424 } | 2434 } |
| 2425 | 2435 |
| 2426 | 2436 |
| 2427 void Map::DeprecateTransitionTree() { | 2437 void Map::DeprecateTransitionTree() { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2555 // FindUpdatedMap. This uses the keys in the own map's descriptor array to | 2565 // FindUpdatedMap. This uses the keys in the own map's descriptor array to |
| 2556 // walk the transition tree. | 2566 // walk the transition tree. |
| 2557 // - Merge/generalize the descriptor array of the current map and |updated|. | 2567 // - Merge/generalize the descriptor array of the current map and |updated|. |
| 2558 // - Generalize the |modify_index| descriptor using |new_representation|. | 2568 // - Generalize the |modify_index| descriptor using |new_representation|. |
| 2559 // - Walk the tree again starting from the root towards |updated|. Stop at | 2569 // - Walk the tree again starting from the root towards |updated|. Stop at |
| 2560 // |split_map|, the first map who's descriptor array does not match the merged | 2570 // |split_map|, the first map who's descriptor array does not match the merged |
| 2561 // descriptor array. | 2571 // descriptor array. |
| 2562 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2572 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
| 2563 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2573 // - Otherwise, invalidate the outdated transition target from |updated|, and |
| 2564 // replace its transition tree with a new branch for the updated descriptors. | 2574 // replace its transition tree with a new branch for the updated descriptors. |
| 2565 MaybeObject* Map::GeneralizeRepresentation(int modify_index, | 2575 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
| 2566 Representation new_representation, | 2576 int modify_index, |
| 2567 StoreMode store_mode) { | 2577 Representation new_representation, |
| 2568 Map* old_map = this; | 2578 StoreMode store_mode) { |
| 2569 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2579 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
| 2570 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2580 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2571 Representation old_representation = old_details.representation(); | 2581 Representation old_representation = old_details.representation(); |
| 2572 | 2582 |
| 2573 // It's fine to transition from None to anything but double without any | 2583 // It's fine to transition from None to anything but double without any |
| 2574 // modification to the object, because the default uninitialized value for | 2584 // modification to the object, because the default uninitialized value for |
| 2575 // representation None can be overwritten by both smi and tagged values. | 2585 // representation None can be overwritten by both smi and tagged values. |
| 2576 // Doubles, however, would require a box allocation. | 2586 // Doubles, however, would require a box allocation. |
| 2577 if (old_representation.IsNone() && | 2587 if (old_representation.IsNone() && |
| 2578 !new_representation.IsNone() && | 2588 !new_representation.IsNone() && |
| 2579 !new_representation.IsDouble()) { | 2589 !new_representation.IsDouble()) { |
| 2580 old_descriptors->SetRepresentation(modify_index, new_representation); | 2590 old_descriptors->SetRepresentation(modify_index, new_representation); |
| 2581 return old_map; | 2591 return old_map; |
| 2582 } | 2592 } |
| 2583 | 2593 |
| 2584 int descriptors = old_map->NumberOfOwnDescriptors(); | 2594 int descriptors = old_map->NumberOfOwnDescriptors(); |
| 2585 Map* root_map = old_map->FindRootMap(); | 2595 Handle<Map> root_map(old_map->FindRootMap()); |
| 2586 | 2596 |
| 2587 // Check the state of the root map. | 2597 // Check the state of the root map. |
| 2588 if (!old_map->EquivalentToForTransition(root_map)) { | 2598 if (!old_map->EquivalentToForTransition(*root_map)) { |
| 2589 return CopyGeneralizeAllRepresentations( | 2599 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2590 modify_index, store_mode, old_details.attributes(), "not equivalent"); | 2600 old_details.attributes(), "not equivalent"); |
| 2591 } | 2601 } |
| 2592 | 2602 |
| 2593 int verbatim = root_map->NumberOfOwnDescriptors(); | 2603 int verbatim = root_map->NumberOfOwnDescriptors(); |
| 2594 | 2604 |
| 2595 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2605 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
| 2596 return CopyGeneralizeAllRepresentations( | 2606 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2597 modify_index, store_mode, | |
| 2598 old_details.attributes(), "root modification"); | 2607 old_details.attributes(), "root modification"); |
| 2599 } | 2608 } |
| 2600 | 2609 |
| 2601 Map* updated = root_map->FindUpdatedMap( | 2610 Map* raw_updated = root_map->FindUpdatedMap( |
| 2602 verbatim, descriptors, old_descriptors); | 2611 verbatim, descriptors, *old_descriptors); |
| 2603 if (updated == NULL) { | 2612 if (raw_updated == NULL) { |
| 2604 return CopyGeneralizeAllRepresentations( | 2613 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2605 modify_index, store_mode, old_details.attributes(), "incompatible"); | 2614 old_details.attributes(), "incompatible"); |
| 2606 } | 2615 } |
| 2607 | 2616 |
| 2608 DescriptorArray* updated_descriptors = updated->instance_descriptors(); | 2617 Handle<Map> updated(raw_updated); |
| 2618 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); |
| 2609 | 2619 |
| 2610 int valid = updated->NumberOfOwnDescriptors(); | 2620 int valid = updated->NumberOfOwnDescriptors(); |
| 2611 | 2621 |
| 2612 // Directly change the map if the target map is more general. Ensure that the | 2622 // Directly change the map if the target map is more general. Ensure that the |
| 2613 // target type of the modify_index is a FIELD, unless we are migrating. | 2623 // target type of the modify_index is a FIELD, unless we are migrating. |
| 2614 if (updated_descriptors->IsMoreGeneralThan( | 2624 if (updated_descriptors->IsMoreGeneralThan( |
| 2615 verbatim, valid, descriptors, old_descriptors) && | 2625 verbatim, valid, descriptors, *old_descriptors) && |
| 2616 (store_mode == ALLOW_AS_CONSTANT || | 2626 (store_mode == ALLOW_AS_CONSTANT || |
| 2617 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2627 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
| 2618 Representation updated_representation = | 2628 Representation updated_representation = |
| 2619 updated_descriptors->GetDetails(modify_index).representation(); | 2629 updated_descriptors->GetDetails(modify_index).representation(); |
| 2620 if (new_representation.fits_into(updated_representation)) return updated; | 2630 if (new_representation.fits_into(updated_representation)) return updated; |
| 2621 } | 2631 } |
| 2622 | 2632 |
| 2623 DescriptorArray* new_descriptors; | 2633 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( |
| 2624 MaybeObject* maybe_descriptors = updated_descriptors->Merge( | 2634 updated_descriptors, verbatim, valid, descriptors, modify_index, |
| 2625 verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); | 2635 store_mode, old_descriptors); |
| 2626 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | |
| 2627 ASSERT(store_mode == ALLOW_AS_CONSTANT || | 2636 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
| 2628 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2637 new_descriptors->GetDetails(modify_index).type() == FIELD); |
| 2629 | 2638 |
| 2630 old_representation = | 2639 old_representation = |
| 2631 new_descriptors->GetDetails(modify_index).representation(); | 2640 new_descriptors->GetDetails(modify_index).representation(); |
| 2632 Representation updated_representation = | 2641 Representation updated_representation = |
| 2633 new_representation.generalize(old_representation); | 2642 new_representation.generalize(old_representation); |
| 2634 if (!updated_representation.Equals(old_representation)) { | 2643 if (!updated_representation.Equals(old_representation)) { |
| 2635 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2644 new_descriptors->SetRepresentation(modify_index, updated_representation); |
| 2636 } | 2645 } |
| 2637 | 2646 |
| 2638 Map* split_map = root_map->FindLastMatchMap( | 2647 Handle<Map> split_map(root_map->FindLastMatchMap( |
| 2639 verbatim, descriptors, new_descriptors); | 2648 verbatim, descriptors, *new_descriptors)); |
| 2640 | 2649 |
| 2641 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2650 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
| 2642 // This is shadowed by |updated_descriptors| being more general than | 2651 // This is shadowed by |updated_descriptors| being more general than |
| 2643 // |old_descriptors|. | 2652 // |old_descriptors|. |
| 2644 ASSERT(descriptors != split_descriptors); | 2653 ASSERT(descriptors != split_descriptors); |
| 2645 | 2654 |
| 2646 int descriptor = split_descriptors; | 2655 int descriptor = split_descriptors; |
| 2647 split_map->DeprecateTarget( | 2656 split_map->DeprecateTarget( |
| 2648 old_descriptors->GetKey(descriptor), new_descriptors); | 2657 old_descriptors->GetKey(descriptor), *new_descriptors); |
| 2649 | 2658 |
| 2650 if (FLAG_trace_generalization) { | 2659 if (FLAG_trace_generalization) { |
| 2651 PrintGeneralization( | 2660 old_map->PrintGeneralization( |
| 2652 stdout, "", modify_index, descriptor, descriptors, | 2661 stdout, "", modify_index, descriptor, descriptors, |
| 2653 old_descriptors->GetDetails(modify_index).type() == CONSTANT && | 2662 old_descriptors->GetDetails(modify_index).type() == CONSTANT && |
| 2654 store_mode == FORCE_FIELD, | 2663 store_mode == FORCE_FIELD, |
| 2655 old_representation, updated_representation); | 2664 old_representation, updated_representation); |
| 2656 } | 2665 } |
| 2657 | 2666 |
| 2658 Map* new_map = split_map; | |
| 2659 // Add missing transitions. | 2667 // Add missing transitions. |
| 2668 Handle<Map> new_map = split_map; |
| 2660 for (; descriptor < descriptors; descriptor++) { | 2669 for (; descriptor < descriptors; descriptor++) { |
| 2661 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( | 2670 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
| 2662 descriptor, new_descriptors); | |
| 2663 if (!maybe_map->To(&new_map)) { | |
| 2664 // Create a handle for the last created map to ensure it stays alive | |
| 2665 // during GC. Its descriptor array is too large, but it will be | |
| 2666 // overwritten during retry anyway. | |
| 2667 Handle<Map>(new_map); | |
| 2668 return maybe_map; | |
| 2669 } | |
| 2670 new_map->set_migration_target(true); | 2671 new_map->set_migration_target(true); |
| 2671 } | 2672 } |
| 2672 | 2673 |
| 2673 new_map->set_owns_descriptors(true); | 2674 new_map->set_owns_descriptors(true); |
| 2674 return new_map; | 2675 return new_map; |
| 2675 } | 2676 } |
| 2676 | 2677 |
| 2677 | 2678 |
| 2678 Map* Map::CurrentMapForDeprecated() { | 2679 Map* Map::CurrentMapForDeprecated() { |
| 2679 DisallowHeapAllocation no_allocation; | 2680 DisallowHeapAllocation no_allocation; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2696 int valid = updated->NumberOfOwnDescriptors(); | 2697 int valid = updated->NumberOfOwnDescriptors(); |
| 2697 if (!updated_descriptors->IsMoreGeneralThan( | 2698 if (!updated_descriptors->IsMoreGeneralThan( |
| 2698 verbatim, valid, descriptors, old_descriptors)) { | 2699 verbatim, valid, descriptors, old_descriptors)) { |
| 2699 return NULL; | 2700 return NULL; |
| 2700 } | 2701 } |
| 2701 | 2702 |
| 2702 return updated; | 2703 return updated; |
| 2703 } | 2704 } |
| 2704 | 2705 |
| 2705 | 2706 |
| 2706 MaybeObject* JSObject::SetPropertyWithInterceptor( | 2707 Handle<Object> JSObject::SetPropertyWithInterceptor( |
| 2707 Name* name, | 2708 Handle<JSObject> object, |
| 2708 Object* value, | 2709 Handle<Name> name, |
| 2710 Handle<Object> value, |
| 2709 PropertyAttributes attributes, | 2711 PropertyAttributes attributes, |
| 2710 StrictModeFlag strict_mode) { | 2712 StrictModeFlag strict_mode) { |
| 2711 // TODO(rossberg): Support symbols in the API. | 2713 // TODO(rossberg): Support symbols in the API. |
| 2712 if (name->IsSymbol()) return value; | 2714 if (name->IsSymbol()) return value; |
| 2713 Isolate* isolate = GetIsolate(); | 2715 Isolate* isolate = object->GetIsolate(); |
| 2714 HandleScope scope(isolate); | 2716 Handle<String> name_string = Handle<String>::cast(name); |
| 2715 Handle<JSObject> this_handle(this); | 2717 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
| 2716 Handle<String> name_handle(String::cast(name)); | |
| 2717 Handle<Object> value_handle(value, isolate); | |
| 2718 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | |
| 2719 if (!interceptor->setter()->IsUndefined()) { | 2718 if (!interceptor->setter()->IsUndefined()) { |
| 2720 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 2719 LOG(isolate, |
| 2721 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 2720 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); |
| 2721 PropertyCallbackArguments args( |
| 2722 isolate, interceptor->data(), *object, *object); |
| 2722 v8::NamedPropertySetterCallback setter = | 2723 v8::NamedPropertySetterCallback setter = |
| 2723 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); | 2724 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |
| 2724 Handle<Object> value_unhole(value->IsTheHole() ? | 2725 Handle<Object> value_unhole = value->IsTheHole() |
| 2725 isolate->heap()->undefined_value() : | 2726 ? Handle<Object>(isolate->factory()->undefined_value()) : value; |
| 2726 value, | |
| 2727 isolate); | |
| 2728 v8::Handle<v8::Value> result = args.Call(setter, | 2727 v8::Handle<v8::Value> result = args.Call(setter, |
| 2729 v8::Utils::ToLocal(name_handle), | 2728 v8::Utils::ToLocal(name_string), |
| 2730 v8::Utils::ToLocal(value_unhole)); | 2729 v8::Utils::ToLocal(value_unhole)); |
| 2731 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2730 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2732 if (!result.IsEmpty()) return *value_handle; | 2731 if (!result.IsEmpty()) return value; |
| 2733 } | 2732 } |
| 2734 MaybeObject* raw_result = | 2733 Handle<Object> result = |
| 2735 this_handle->SetPropertyPostInterceptor(*name_handle, | 2734 SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); |
| 2736 *value_handle, | 2735 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2737 attributes, | 2736 return result; |
| 2738 strict_mode); | |
| 2739 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 2740 return raw_result; | |
| 2741 } | 2737 } |
| 2742 | 2738 |
| 2743 | 2739 |
| 2744 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 2740 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 2745 Handle<Name> key, | 2741 Handle<Name> name, |
| 2746 Handle<Object> value, | 2742 Handle<Object> value, |
| 2747 PropertyAttributes attributes, | 2743 PropertyAttributes attributes, |
| 2748 StrictModeFlag strict_mode) { | 2744 StrictModeFlag strict_mode, |
| 2749 CALL_HEAP_FUNCTION(object->GetIsolate(), | 2745 StoreFromKeyed store_mode) { |
| 2750 object->SetProperty(*key, *value, attributes, strict_mode), | 2746 LookupResult result(object->GetIsolate()); |
| 2751 Object); | 2747 object->LocalLookup(*name, &result, true); |
| 2748 if (!result.IsFound()) { |
| 2749 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); |
| 2750 } |
| 2751 return SetProperty(object, &result, name, value, attributes, strict_mode, |
| 2752 store_mode); |
| 2752 } | 2753 } |
| 2753 | 2754 |
| 2754 | 2755 |
| 2755 MaybeObject* JSReceiver::SetPropertyOrFail( | 2756 Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object, |
| 2756 Handle<JSReceiver> object, | 2757 Handle<Object> structure, |
| 2757 Handle<Name> key, | 2758 Handle<Name> name, |
| 2758 Handle<Object> value, | 2759 Handle<Object> value, |
| 2759 PropertyAttributes attributes, | 2760 Handle<JSObject> holder, |
| 2760 StrictModeFlag strict_mode, | 2761 StrictModeFlag strict_mode) { |
| 2761 JSReceiver::StoreFromKeyed store_mode) { | 2762 Isolate* isolate = object->GetIsolate(); |
| 2762 CALL_HEAP_FUNCTION_PASS_EXCEPTION( | |
| 2763 object->GetIsolate(), | |
| 2764 object->SetProperty(*key, *value, attributes, strict_mode, store_mode)); | |
| 2765 } | |
| 2766 | |
| 2767 | |
| 2768 MaybeObject* JSReceiver::SetProperty(Name* name, | |
| 2769 Object* value, | |
| 2770 PropertyAttributes attributes, | |
| 2771 StrictModeFlag strict_mode, | |
| 2772 JSReceiver::StoreFromKeyed store_mode) { | |
| 2773 LookupResult result(GetIsolate()); | |
| 2774 LocalLookup(name, &result, true); | |
| 2775 if (!result.IsFound()) { | |
| 2776 map()->LookupTransition(JSObject::cast(this), name, &result); | |
| 2777 } | |
| 2778 return SetProperty(&result, name, value, attributes, strict_mode, store_mode); | |
| 2779 } | |
| 2780 | |
| 2781 | |
| 2782 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | |
| 2783 Name* name, | |
| 2784 Object* value, | |
| 2785 JSObject* holder, | |
| 2786 StrictModeFlag strict_mode) { | |
| 2787 Isolate* isolate = GetIsolate(); | |
| 2788 HandleScope scope(isolate); | |
| 2789 | 2763 |
| 2790 // We should never get here to initialize a const with the hole | 2764 // We should never get here to initialize a const with the hole |
| 2791 // value since a const declaration would conflict with the setter. | 2765 // value since a const declaration would conflict with the setter. |
| 2792 ASSERT(!value->IsTheHole()); | 2766 ASSERT(!value->IsTheHole()); |
| 2793 Handle<Object> value_handle(value, isolate); | |
| 2794 | 2767 |
| 2795 // To accommodate both the old and the new api we switch on the | 2768 // To accommodate both the old and the new api we switch on the |
| 2796 // data structure used to store the callbacks. Eventually foreign | 2769 // data structure used to store the callbacks. Eventually foreign |
| 2797 // callbacks should be phased out. | 2770 // callbacks should be phased out. |
| 2798 if (structure->IsForeign()) { | 2771 if (structure->IsForeign()) { |
| 2799 AccessorDescriptor* callback = | 2772 AccessorDescriptor* callback = |
| 2800 reinterpret_cast<AccessorDescriptor*>( | 2773 reinterpret_cast<AccessorDescriptor*>( |
| 2801 Foreign::cast(structure)->foreign_address()); | 2774 Handle<Foreign>::cast(structure)->foreign_address()); |
| 2802 MaybeObject* obj = (callback->setter)( | 2775 CALL_AND_RETRY_OR_DIE(isolate, |
| 2803 isolate, this, value, callback->data); | 2776 (callback->setter)( |
| 2804 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2777 isolate, *object, *value, callback->data), |
| 2805 if (obj->IsFailure()) return obj; | 2778 break, |
| 2806 return *value_handle; | 2779 return Handle<Object>()); |
| 2780 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2781 return value; |
| 2807 } | 2782 } |
| 2808 | 2783 |
| 2809 if (structure->IsExecutableAccessorInfo()) { | 2784 if (structure->IsExecutableAccessorInfo()) { |
| 2810 // api style callbacks | 2785 // api style callbacks |
| 2811 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); | 2786 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure); |
| 2812 if (!data->IsCompatibleReceiver(this)) { | 2787 if (!data->IsCompatibleReceiver(*object)) { |
| 2813 Handle<Object> name_handle(name, isolate); | 2788 Handle<Object> args[2] = { name, object }; |
| 2814 Handle<Object> receiver_handle(this, isolate); | |
| 2815 Handle<Object> args[2] = { name_handle, receiver_handle }; | |
| 2816 Handle<Object> error = | 2789 Handle<Object> error = |
| 2817 isolate->factory()->NewTypeError("incompatible_method_receiver", | 2790 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 2818 HandleVector(args, | 2791 HandleVector(args, |
| 2819 ARRAY_SIZE(args))); | 2792 ARRAY_SIZE(args))); |
| 2820 return isolate->Throw(*error); | 2793 isolate->Throw(*error); |
| 2794 return Handle<Object>(); |
| 2821 } | 2795 } |
| 2822 // TODO(rossberg): Support symbols in the API. | 2796 // TODO(rossberg): Support symbols in the API. |
| 2823 if (name->IsSymbol()) return value; | 2797 if (name->IsSymbol()) return value; |
| 2824 Object* call_obj = data->setter(); | 2798 Object* call_obj = data->setter(); |
| 2825 v8::AccessorSetterCallback call_fun = | 2799 v8::AccessorSetterCallback call_fun = |
| 2826 v8::ToCData<v8::AccessorSetterCallback>(call_obj); | 2800 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 2827 if (call_fun == NULL) return value; | 2801 if (call_fun == NULL) return value; |
| 2828 Handle<String> key(String::cast(name)); | 2802 Handle<String> key = Handle<String>::cast(name); |
| 2829 LOG(isolate, ApiNamedPropertyAccess("store", this, name)); | 2803 LOG(isolate, ApiNamedPropertyAccess("store", *object, *name)); |
| 2830 PropertyCallbackArguments args( | 2804 PropertyCallbackArguments args( |
| 2831 isolate, data->data(), this, JSObject::cast(holder)); | 2805 isolate, data->data(), *object, JSObject::cast(*holder)); |
| 2832 args.Call(call_fun, | 2806 args.Call(call_fun, |
| 2833 v8::Utils::ToLocal(key), | 2807 v8::Utils::ToLocal(key), |
| 2834 v8::Utils::ToLocal(value_handle)); | 2808 v8::Utils::ToLocal(value)); |
| 2835 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2809 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2836 return *value_handle; | 2810 return value; |
| 2837 } | 2811 } |
| 2838 | 2812 |
| 2839 if (structure->IsAccessorPair()) { | 2813 if (structure->IsAccessorPair()) { |
| 2840 Object* setter = AccessorPair::cast(structure)->setter(); | 2814 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
| 2841 if (setter->IsSpecFunction()) { | 2815 if (setter->IsSpecFunction()) { |
| 2842 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 2816 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 2843 return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value); | 2817 return SetPropertyWithDefinedSetter( |
| 2818 object, Handle<JSReceiver>::cast(setter), value); |
| 2844 } else { | 2819 } else { |
| 2845 if (strict_mode == kNonStrictMode) { | 2820 if (strict_mode == kNonStrictMode) { |
| 2846 return value; | 2821 return value; |
| 2847 } | 2822 } |
| 2848 Handle<Name> key(name); | 2823 Handle<Object> args[2] = { name, holder }; |
| 2849 Handle<Object> holder_handle(holder, isolate); | 2824 Handle<Object> error = |
| 2850 Handle<Object> args[2] = { key, holder_handle }; | 2825 isolate->factory()->NewTypeError("no_setter_in_callback", |
| 2851 return isolate->Throw( | 2826 HandleVector(args, 2)); |
| 2852 *isolate->factory()->NewTypeError("no_setter_in_callback", | 2827 isolate->Throw(*error); |
| 2853 HandleVector(args, 2))); | 2828 return Handle<Object>(); |
| 2854 } | 2829 } |
| 2855 } | 2830 } |
| 2856 | 2831 |
| 2857 // TODO(dcarney): Handle correctly. | 2832 // TODO(dcarney): Handle correctly. |
| 2858 if (structure->IsDeclaredAccessorInfo()) { | 2833 if (structure->IsDeclaredAccessorInfo()) { |
| 2859 return value; | 2834 return value; |
| 2860 } | 2835 } |
| 2861 | 2836 |
| 2862 UNREACHABLE(); | 2837 UNREACHABLE(); |
| 2863 return NULL; | 2838 return Handle<Object>(); |
| 2864 } | 2839 } |
| 2865 | 2840 |
| 2866 | 2841 |
| 2867 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter, | 2842 Handle<Object> JSReceiver::SetPropertyWithDefinedSetter( |
| 2868 Object* value) { | 2843 Handle<JSReceiver> object, |
| 2869 Isolate* isolate = GetIsolate(); | 2844 Handle<JSReceiver> setter, |
| 2870 Handle<Object> value_handle(value, isolate); | 2845 Handle<Object> value) { |
| 2871 Handle<JSReceiver> fun(setter, isolate); | 2846 Isolate* isolate = object->GetIsolate(); |
| 2872 Handle<JSReceiver> self(this, isolate); | 2847 |
| 2873 #ifdef ENABLE_DEBUGGER_SUPPORT | 2848 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 2874 Debug* debug = isolate->debug(); | 2849 Debug* debug = isolate->debug(); |
| 2875 // Handle stepping into a setter if step into is active. | 2850 // Handle stepping into a setter if step into is active. |
| 2876 // TODO(rossberg): should this apply to getters that are function proxies? | 2851 // TODO(rossberg): should this apply to getters that are function proxies? |
| 2877 if (debug->StepInActive() && fun->IsJSFunction()) { | 2852 if (debug->StepInActive() && setter->IsJSFunction()) { |
| 2878 debug->HandleStepIn( | 2853 debug->HandleStepIn( |
| 2879 Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false); | 2854 Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false); |
| 2880 } | 2855 } |
| 2881 #endif | 2856 #endif |
| 2857 |
| 2882 bool has_pending_exception; | 2858 bool has_pending_exception; |
| 2883 Handle<Object> argv[] = { value_handle }; | 2859 Handle<Object> argv[] = { value }; |
| 2884 Execution::Call( | 2860 Execution::Call( |
| 2885 isolate, fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception); | 2861 isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 2886 // Check for pending exception and return the result. | 2862 // Check for pending exception and return the result. |
| 2887 if (has_pending_exception) return Failure::Exception(); | 2863 if (has_pending_exception) return Handle<Object>(); |
| 2888 return *value_handle; | 2864 return value; |
| 2889 } | 2865 } |
| 2890 | 2866 |
| 2891 | 2867 |
| 2892 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( | 2868 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( |
| 2893 uint32_t index, | 2869 uint32_t index, |
| 2894 Object* value, | 2870 Object* value, |
| 2895 bool* found, | 2871 bool* found, |
| 2896 StrictModeFlag strict_mode) { | 2872 StrictModeFlag strict_mode) { |
| 2897 Heap* heap = GetHeap(); | 2873 Heap* heap = GetHeap(); |
| 2898 for (Object* pt = GetPrototype(); | 2874 for (Object* pt = GetPrototype(); |
| 2899 pt != heap->null_value(); | 2875 pt != heap->null_value(); |
| 2900 pt = pt->GetPrototype(GetIsolate())) { | 2876 pt = pt->GetPrototype(GetIsolate())) { |
| 2901 if (pt->IsJSProxy()) { | 2877 if (pt->IsJSProxy()) { |
| 2902 String* name; | 2878 Isolate* isolate = GetIsolate(); |
| 2903 MaybeObject* maybe = heap->Uint32ToString(index); | 2879 HandleScope scope(isolate); |
| 2904 if (!maybe->To<String>(&name)) { | 2880 Handle<JSProxy> proxy(JSProxy::cast(pt)); |
| 2905 *found = true; // Force abort | 2881 Handle<JSObject> self(this, isolate); |
| 2906 return maybe; | 2882 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 2907 } | 2883 Handle<Object> value_handle(value, isolate); |
| 2908 return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler( | 2884 Handle<Object> result = JSProxy::SetPropertyViaPrototypesWithHandler( |
| 2909 this, name, value, NONE, strict_mode, found); | 2885 proxy, self, name, value_handle, NONE, strict_mode, found); |
| 2886 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 2887 return *result; |
| 2910 } | 2888 } |
| 2911 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 2889 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 2912 continue; | 2890 continue; |
| 2913 } | 2891 } |
| 2914 SeededNumberDictionary* dictionary = | 2892 SeededNumberDictionary* dictionary = |
| 2915 JSObject::cast(pt)->element_dictionary(); | 2893 JSObject::cast(pt)->element_dictionary(); |
| 2916 int entry = dictionary->FindEntry(index); | 2894 int entry = dictionary->FindEntry(index); |
| 2917 if (entry != SeededNumberDictionary::kNotFound) { | 2895 if (entry != SeededNumberDictionary::kNotFound) { |
| 2918 PropertyDetails details = dictionary->DetailsAt(entry); | 2896 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2919 if (details.type() == CALLBACKS) { | 2897 if (details.type() == CALLBACKS) { |
| 2920 *found = true; | 2898 *found = true; |
| 2921 return SetElementWithCallback(dictionary->ValueAt(entry), | 2899 Isolate* isolate = GetIsolate(); |
| 2922 index, | 2900 HandleScope scope(isolate); |
| 2923 value, | 2901 Handle<JSObject> self(this, isolate); |
| 2924 JSObject::cast(pt), | 2902 Handle<Object> structure(dictionary->ValueAt(entry), isolate); |
| 2925 strict_mode); | 2903 Handle<Object> value_handle(value, isolate); |
| 2904 Handle<JSObject> holder(JSObject::cast(pt)); |
| 2905 Handle<Object> result = SetElementWithCallback( |
| 2906 self, structure, index, value_handle, holder, strict_mode); |
| 2907 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 2908 return *result; |
| 2926 } | 2909 } |
| 2927 } | 2910 } |
| 2928 } | 2911 } |
| 2929 *found = false; | 2912 *found = false; |
| 2930 return heap->the_hole_value(); | 2913 return heap->the_hole_value(); |
| 2931 } | 2914 } |
| 2932 | 2915 |
| 2933 MaybeObject* JSObject::SetPropertyViaPrototypes( | 2916 |
| 2934 Name* name, | 2917 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
| 2935 Object* value, | 2918 Handle<Name> name, |
| 2936 PropertyAttributes attributes, | 2919 Handle<Object> value, |
| 2937 StrictModeFlag strict_mode, | 2920 PropertyAttributes attributes, |
| 2938 bool* done) { | 2921 StrictModeFlag strict_mode, |
| 2939 Heap* heap = GetHeap(); | 2922 bool* done) { |
| 2940 Isolate* isolate = heap->isolate(); | 2923 Isolate* isolate = object->GetIsolate(); |
| 2941 | 2924 |
| 2942 *done = false; | 2925 *done = false; |
| 2943 // We could not find a local property so let's check whether there is an | 2926 // We could not find a local property so let's check whether there is an |
| 2944 // accessor that wants to handle the property, or whether the property is | 2927 // accessor that wants to handle the property, or whether the property is |
| 2945 // read-only on the prototype chain. | 2928 // read-only on the prototype chain. |
| 2946 LookupResult result(isolate); | 2929 LookupResult result(isolate); |
| 2947 LookupRealNamedPropertyInPrototypes(name, &result); | 2930 object->LookupRealNamedPropertyInPrototypes(*name, &result); |
| 2948 if (result.IsFound()) { | 2931 if (result.IsFound()) { |
| 2949 switch (result.type()) { | 2932 switch (result.type()) { |
| 2950 case NORMAL: | 2933 case NORMAL: |
| 2951 case FIELD: | 2934 case FIELD: |
| 2952 case CONSTANT: | 2935 case CONSTANT: |
| 2953 *done = result.IsReadOnly(); | 2936 *done = result.IsReadOnly(); |
| 2954 break; | 2937 break; |
| 2955 case INTERCEPTOR: { | 2938 case INTERCEPTOR: { |
| 2956 PropertyAttributes attr = | 2939 PropertyAttributes attr = |
| 2957 result.holder()->GetPropertyAttributeWithInterceptor( | 2940 result.holder()->GetPropertyAttributeWithInterceptor( |
| 2958 this, name, true); | 2941 *object, *name, true); |
| 2959 *done = !!(attr & READ_ONLY); | 2942 *done = !!(attr & READ_ONLY); |
| 2960 break; | 2943 break; |
| 2961 } | 2944 } |
| 2962 case CALLBACKS: { | 2945 case CALLBACKS: { |
| 2963 if (!FLAG_es5_readonly && result.IsReadOnly()) break; | 2946 if (!FLAG_es5_readonly && result.IsReadOnly()) break; |
| 2964 *done = true; | 2947 *done = true; |
| 2965 return SetPropertyWithCallback(result.GetCallbackObject(), | 2948 Handle<Object> callback_object(result.GetCallbackObject(), isolate); |
| 2966 name, value, result.holder(), strict_mode); | 2949 return SetPropertyWithCallback(object, callback_object, name, value, |
| 2950 handle(result.holder()), strict_mode); |
| 2967 } | 2951 } |
| 2968 case HANDLER: { | 2952 case HANDLER: { |
| 2969 return result.proxy()->SetPropertyViaPrototypesWithHandler( | 2953 Handle<JSProxy> proxy(result.proxy()); |
| 2970 this, name, value, attributes, strict_mode, done); | 2954 return JSProxy::SetPropertyViaPrototypesWithHandler( |
| 2955 proxy, object, name, value, attributes, strict_mode, done); |
| 2971 } | 2956 } |
| 2972 case TRANSITION: | 2957 case TRANSITION: |
| 2973 case NONEXISTENT: | 2958 case NONEXISTENT: |
| 2974 UNREACHABLE(); | 2959 UNREACHABLE(); |
| 2975 break; | 2960 break; |
| 2976 } | 2961 } |
| 2977 } | 2962 } |
| 2978 | 2963 |
| 2979 // If we get here with *done true, we have encountered a read-only property. | 2964 // If we get here with *done true, we have encountered a read-only property. |
| 2980 if (!FLAG_es5_readonly) *done = false; | 2965 if (!FLAG_es5_readonly) *done = false; |
| 2981 if (*done) { | 2966 if (*done) { |
| 2982 if (strict_mode == kNonStrictMode) return value; | 2967 if (strict_mode == kNonStrictMode) return value; |
| 2983 Handle<Object> args[] = { Handle<Object>(name, isolate), | 2968 Handle<Object> args[] = { name, object }; |
| 2984 Handle<Object>(this, isolate)}; | 2969 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2985 return isolate->Throw(*isolate->factory()->NewTypeError( | 2970 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 2986 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 2971 isolate->Throw(*error); |
| 2972 return Handle<Object>(); |
| 2987 } | 2973 } |
| 2988 return heap->the_hole_value(); | 2974 return isolate->factory()->the_hole_value(); |
| 2989 } | 2975 } |
| 2990 | 2976 |
| 2991 | 2977 |
| 2992 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { | 2978 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
| 2993 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2979 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 2994 if (slack <= descriptors->NumberOfSlackDescriptors()) return; | 2980 if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
| 2995 int number_of_descriptors = descriptors->number_of_descriptors(); | 2981 int number_of_descriptors = descriptors->number_of_descriptors(); |
| 2996 Isolate* isolate = map->GetIsolate(); | 2982 Isolate* isolate = map->GetIsolate(); |
| 2997 Handle<DescriptorArray> new_descriptors = | 2983 Handle<DescriptorArray> new_descriptors = |
| 2998 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); | 2984 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3333 } | 3319 } |
| 3334 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 3320 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 3335 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); | 3321 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); |
| 3336 if (result->IsFound()) return; | 3322 if (result->IsFound()) return; |
| 3337 } | 3323 } |
| 3338 result->NotFound(); | 3324 result->NotFound(); |
| 3339 } | 3325 } |
| 3340 | 3326 |
| 3341 | 3327 |
| 3342 // We only need to deal with CALLBACKS and INTERCEPTORS | 3328 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 3343 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck( | 3329 Handle<Object> JSObject::SetPropertyWithFailedAccessCheck( |
| 3330 Handle<JSObject> object, |
| 3344 LookupResult* result, | 3331 LookupResult* result, |
| 3345 Name* name, | 3332 Handle<Name> name, |
| 3346 Object* value, | 3333 Handle<Object> value, |
| 3347 bool check_prototype, | 3334 bool check_prototype, |
| 3348 StrictModeFlag strict_mode) { | 3335 StrictModeFlag strict_mode) { |
| 3349 if (check_prototype && !result->IsProperty()) { | 3336 if (check_prototype && !result->IsProperty()) { |
| 3350 LookupRealNamedPropertyInPrototypes(name, result); | 3337 object->LookupRealNamedPropertyInPrototypes(*name, result); |
| 3351 } | 3338 } |
| 3352 | 3339 |
| 3353 if (result->IsProperty()) { | 3340 if (result->IsProperty()) { |
| 3354 if (!result->IsReadOnly()) { | 3341 if (!result->IsReadOnly()) { |
| 3355 switch (result->type()) { | 3342 switch (result->type()) { |
| 3356 case CALLBACKS: { | 3343 case CALLBACKS: { |
| 3357 Object* obj = result->GetCallbackObject(); | 3344 Object* obj = result->GetCallbackObject(); |
| 3358 if (obj->IsAccessorInfo()) { | 3345 if (obj->IsAccessorInfo()) { |
| 3359 AccessorInfo* info = AccessorInfo::cast(obj); | 3346 Handle<AccessorInfo> info(AccessorInfo::cast(obj)); |
| 3360 if (info->all_can_write()) { | 3347 if (info->all_can_write()) { |
| 3361 return SetPropertyWithCallback(result->GetCallbackObject(), | 3348 return SetPropertyWithCallback(object, |
| 3349 info, |
| 3362 name, | 3350 name, |
| 3363 value, | 3351 value, |
| 3364 result->holder(), | 3352 handle(result->holder()), |
| 3365 strict_mode); | 3353 strict_mode); |
| 3366 } | 3354 } |
| 3367 } else if (obj->IsAccessorPair()) { | 3355 } else if (obj->IsAccessorPair()) { |
| 3368 AccessorPair* pair = AccessorPair::cast(obj); | 3356 Handle<AccessorPair> pair(AccessorPair::cast(obj)); |
| 3369 if (pair->all_can_read()) { | 3357 if (pair->all_can_read()) { |
| 3370 return SetPropertyWithCallback(result->GetCallbackObject(), | 3358 return SetPropertyWithCallback(object, |
| 3359 pair, |
| 3371 name, | 3360 name, |
| 3372 value, | 3361 value, |
| 3373 result->holder(), | 3362 handle(result->holder()), |
| 3374 strict_mode); | 3363 strict_mode); |
| 3375 } | 3364 } |
| 3376 } | 3365 } |
| 3377 break; | 3366 break; |
| 3378 } | 3367 } |
| 3379 case INTERCEPTOR: { | 3368 case INTERCEPTOR: { |
| 3380 // Try lookup real named properties. Note that only property can be | 3369 // Try lookup real named properties. Note that only property can be |
| 3381 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | 3370 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. |
| 3382 LookupResult r(GetIsolate()); | 3371 LookupResult r(object->GetIsolate()); |
| 3383 LookupRealNamedProperty(name, &r); | 3372 object->LookupRealNamedProperty(*name, &r); |
| 3384 if (r.IsProperty()) { | 3373 if (r.IsProperty()) { |
| 3385 return SetPropertyWithFailedAccessCheck(&r, | 3374 return SetPropertyWithFailedAccessCheck(object, |
| 3375 &r, |
| 3386 name, | 3376 name, |
| 3387 value, | 3377 value, |
| 3388 check_prototype, | 3378 check_prototype, |
| 3389 strict_mode); | 3379 strict_mode); |
| 3390 } | 3380 } |
| 3391 break; | 3381 break; |
| 3392 } | 3382 } |
| 3393 default: { | 3383 default: { |
| 3394 break; | 3384 break; |
| 3395 } | 3385 } |
| 3396 } | 3386 } |
| 3397 } | 3387 } |
| 3398 } | 3388 } |
| 3399 | 3389 |
| 3400 Isolate* isolate = GetIsolate(); | 3390 Isolate* isolate = object->GetIsolate(); |
| 3401 HandleScope scope(isolate); | 3391 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
| 3402 Handle<Object> value_handle(value, isolate); | 3392 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 3403 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3393 return value; |
| 3404 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 3405 return *value_handle; | |
| 3406 } | 3394 } |
| 3407 | 3395 |
| 3408 | 3396 |
| 3409 MaybeObject* JSReceiver::SetProperty(LookupResult* result, | 3397 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 3410 Name* key, | 3398 LookupResult* result, |
| 3411 Object* value, | 3399 Handle<Name> key, |
| 3412 PropertyAttributes attributes, | 3400 Handle<Object> value, |
| 3413 StrictModeFlag strict_mode, | 3401 PropertyAttributes attributes, |
| 3414 JSReceiver::StoreFromKeyed store_mode) { | 3402 StrictModeFlag strict_mode, |
| 3403 StoreFromKeyed store_mode) { |
| 3415 if (result->IsHandler()) { | 3404 if (result->IsHandler()) { |
| 3416 return result->proxy()->SetPropertyWithHandler( | 3405 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), |
| 3417 this, key, value, attributes, strict_mode); | 3406 object, key, value, attributes, strict_mode); |
| 3418 } else { | 3407 } else { |
| 3419 return JSObject::cast(this)->SetPropertyForResult( | 3408 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object), |
| 3420 result, key, value, attributes, strict_mode, store_mode); | 3409 result, key, value, attributes, strict_mode, store_mode); |
| 3421 } | 3410 } |
| 3422 } | 3411 } |
| 3423 | 3412 |
| 3424 | 3413 |
| 3425 bool JSProxy::HasPropertyWithHandler(Name* name_raw) { | 3414 bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) { |
| 3426 Isolate* isolate = GetIsolate(); | 3415 Isolate* isolate = proxy->GetIsolate(); |
| 3427 HandleScope scope(isolate); | |
| 3428 Handle<Object> receiver(this, isolate); | |
| 3429 Handle<Object> name(name_raw, isolate); | |
| 3430 | 3416 |
| 3431 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3417 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3432 if (name->IsSymbol()) return false; | 3418 if (name->IsSymbol()) return false; |
| 3433 | 3419 |
| 3434 Handle<Object> args[] = { name }; | 3420 Handle<Object> args[] = { name }; |
| 3435 Handle<Object> result = CallTrap( | 3421 Handle<Object> result = proxy->CallTrap( |
| 3436 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); | 3422 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args); |
| 3437 if (isolate->has_pending_exception()) return false; | 3423 if (isolate->has_pending_exception()) return false; |
| 3438 | 3424 |
| 3439 return result->BooleanValue(); | 3425 return result->BooleanValue(); |
| 3440 } | 3426 } |
| 3441 | 3427 |
| 3442 | 3428 |
| 3443 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( | 3429 Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
| 3444 JSReceiver* receiver_raw, | 3430 Handle<JSReceiver> receiver, |
| 3445 Name* name_raw, | 3431 Handle<Name> name, |
| 3446 Object* value_raw, | 3432 Handle<Object> value, |
| 3447 PropertyAttributes attributes, | 3433 PropertyAttributes attributes, |
| 3448 StrictModeFlag strict_mode) { | 3434 StrictModeFlag strict_mode) { |
| 3449 Isolate* isolate = GetIsolate(); | 3435 Isolate* isolate = proxy->GetIsolate(); |
| 3450 HandleScope scope(isolate); | |
| 3451 Handle<JSReceiver> receiver(receiver_raw); | |
| 3452 Handle<Object> name(name_raw, isolate); | |
| 3453 Handle<Object> value(value_raw, isolate); | |
| 3454 | 3436 |
| 3455 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3437 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3456 if (name->IsSymbol()) return *value; | 3438 if (name->IsSymbol()) return value; |
| 3457 | 3439 |
| 3458 Handle<Object> args[] = { receiver, name, value }; | 3440 Handle<Object> args[] = { receiver, name, value }; |
| 3459 CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); | 3441 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); |
| 3460 if (isolate->has_pending_exception()) return Failure::Exception(); | 3442 if (isolate->has_pending_exception()) return Handle<Object>(); |
| 3461 | 3443 |
| 3462 return *value; | 3444 return value; |
| 3463 } | 3445 } |
| 3464 | 3446 |
| 3465 | 3447 |
| 3466 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler( | 3448 Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| 3467 JSReceiver* receiver_raw, | 3449 Handle<JSProxy> proxy, |
| 3468 Name* name_raw, | 3450 Handle<JSReceiver> receiver, |
| 3469 Object* value_raw, | 3451 Handle<Name> name, |
| 3452 Handle<Object> value, |
| 3470 PropertyAttributes attributes, | 3453 PropertyAttributes attributes, |
| 3471 StrictModeFlag strict_mode, | 3454 StrictModeFlag strict_mode, |
| 3472 bool* done) { | 3455 bool* done) { |
| 3473 Isolate* isolate = GetIsolate(); | 3456 Isolate* isolate = proxy->GetIsolate(); |
| 3474 Handle<JSProxy> proxy(this); | 3457 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
| 3475 Handle<JSReceiver> receiver(receiver_raw); | |
| 3476 Handle<Name> name(name_raw); | |
| 3477 Handle<Object> value(value_raw, isolate); | |
| 3478 Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy. | |
| 3479 | 3458 |
| 3480 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3459 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3481 if (name->IsSymbol()) { | 3460 if (name->IsSymbol()) { |
| 3482 *done = false; | 3461 *done = false; |
| 3483 return isolate->heap()->the_hole_value(); | 3462 return isolate->factory()->the_hole_value(); |
| 3484 } | 3463 } |
| 3485 | 3464 |
| 3486 *done = true; // except where redefined... | 3465 *done = true; // except where redefined... |
| 3487 Handle<Object> args[] = { name }; | 3466 Handle<Object> args[] = { name }; |
| 3488 Handle<Object> result = proxy->CallTrap( | 3467 Handle<Object> result = proxy->CallTrap( |
| 3489 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); | 3468 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); |
| 3490 if (isolate->has_pending_exception()) return Failure::Exception(); | 3469 if (isolate->has_pending_exception()) return Handle<Object>(); |
| 3491 | 3470 |
| 3492 if (result->IsUndefined()) { | 3471 if (result->IsUndefined()) { |
| 3493 *done = false; | 3472 *done = false; |
| 3494 return isolate->heap()->the_hole_value(); | 3473 return isolate->factory()->the_hole_value(); |
| 3495 } | 3474 } |
| 3496 | 3475 |
| 3497 // Emulate [[GetProperty]] semantics for proxies. | 3476 // Emulate [[GetProperty]] semantics for proxies. |
| 3498 bool has_pending_exception; | 3477 bool has_pending_exception; |
| 3499 Handle<Object> argv[] = { result }; | 3478 Handle<Object> argv[] = { result }; |
| 3500 Handle<Object> desc = Execution::Call( | 3479 Handle<Object> desc = Execution::Call( |
| 3501 isolate, isolate->to_complete_property_descriptor(), result, | 3480 isolate, isolate->to_complete_property_descriptor(), result, |
| 3502 ARRAY_SIZE(argv), argv, &has_pending_exception); | 3481 ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 3503 if (has_pending_exception) return Failure::Exception(); | 3482 if (has_pending_exception) return Handle<Object>(); |
| 3504 | 3483 |
| 3505 // [[GetProperty]] requires to check that all properties are configurable. | 3484 // [[GetProperty]] requires to check that all properties are configurable. |
| 3506 Handle<String> configurable_name = | 3485 Handle<String> configurable_name = |
| 3507 isolate->factory()->InternalizeOneByteString( | 3486 isolate->factory()->InternalizeOneByteString( |
| 3508 STATIC_ASCII_VECTOR("configurable_")); | 3487 STATIC_ASCII_VECTOR("configurable_")); |
| 3509 Handle<Object> configurable( | 3488 Handle<Object> configurable( |
| 3510 v8::internal::GetProperty(isolate, desc, configurable_name)); | 3489 v8::internal::GetProperty(isolate, desc, configurable_name)); |
| 3511 ASSERT(!isolate->has_pending_exception()); | 3490 ASSERT(!isolate->has_pending_exception()); |
| 3512 ASSERT(configurable->IsTrue() || configurable->IsFalse()); | 3491 ASSERT(configurable->IsTrue() || configurable->IsFalse()); |
| 3513 if (configurable->IsFalse()) { | 3492 if (configurable->IsFalse()) { |
| 3514 Handle<String> trap = | 3493 Handle<String> trap = |
| 3515 isolate->factory()->InternalizeOneByteString( | 3494 isolate->factory()->InternalizeOneByteString( |
| 3516 STATIC_ASCII_VECTOR("getPropertyDescriptor")); | 3495 STATIC_ASCII_VECTOR("getPropertyDescriptor")); |
| 3517 Handle<Object> args[] = { handler, trap, name }; | 3496 Handle<Object> args[] = { handler, trap, name }; |
| 3518 Handle<Object> error = isolate->factory()->NewTypeError( | 3497 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3519 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 3498 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 3520 return isolate->Throw(*error); | 3499 isolate->Throw(*error); |
| 3500 return Handle<Object>(); |
| 3521 } | 3501 } |
| 3522 ASSERT(configurable->IsTrue()); | 3502 ASSERT(configurable->IsTrue()); |
| 3523 | 3503 |
| 3524 // Check for DataDescriptor. | 3504 // Check for DataDescriptor. |
| 3525 Handle<String> hasWritable_name = | 3505 Handle<String> hasWritable_name = |
| 3526 isolate->factory()->InternalizeOneByteString( | 3506 isolate->factory()->InternalizeOneByteString( |
| 3527 STATIC_ASCII_VECTOR("hasWritable_")); | 3507 STATIC_ASCII_VECTOR("hasWritable_")); |
| 3528 Handle<Object> hasWritable( | 3508 Handle<Object> hasWritable( |
| 3529 v8::internal::GetProperty(isolate, desc, hasWritable_name)); | 3509 v8::internal::GetProperty(isolate, desc, hasWritable_name)); |
| 3530 ASSERT(!isolate->has_pending_exception()); | 3510 ASSERT(!isolate->has_pending_exception()); |
| 3531 ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse()); | 3511 ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse()); |
| 3532 if (hasWritable->IsTrue()) { | 3512 if (hasWritable->IsTrue()) { |
| 3533 Handle<String> writable_name = | 3513 Handle<String> writable_name = |
| 3534 isolate->factory()->InternalizeOneByteString( | 3514 isolate->factory()->InternalizeOneByteString( |
| 3535 STATIC_ASCII_VECTOR("writable_")); | 3515 STATIC_ASCII_VECTOR("writable_")); |
| 3536 Handle<Object> writable( | 3516 Handle<Object> writable( |
| 3537 v8::internal::GetProperty(isolate, desc, writable_name)); | 3517 v8::internal::GetProperty(isolate, desc, writable_name)); |
| 3538 ASSERT(!isolate->has_pending_exception()); | 3518 ASSERT(!isolate->has_pending_exception()); |
| 3539 ASSERT(writable->IsTrue() || writable->IsFalse()); | 3519 ASSERT(writable->IsTrue() || writable->IsFalse()); |
| 3540 *done = writable->IsFalse(); | 3520 *done = writable->IsFalse(); |
| 3541 if (!*done) return GetHeap()->the_hole_value(); | 3521 if (!*done) return isolate->factory()->the_hole_value(); |
| 3542 if (strict_mode == kNonStrictMode) return *value; | 3522 if (strict_mode == kNonStrictMode) return value; |
| 3543 Handle<Object> args[] = { name, receiver }; | 3523 Handle<Object> args[] = { name, receiver }; |
| 3544 Handle<Object> error = isolate->factory()->NewTypeError( | 3524 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3545 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 3525 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3546 return isolate->Throw(*error); | 3526 isolate->Throw(*error); |
| 3527 return Handle<Object>(); |
| 3547 } | 3528 } |
| 3548 | 3529 |
| 3549 // We have an AccessorDescriptor. | 3530 // We have an AccessorDescriptor. |
| 3550 Handle<String> set_name = isolate->factory()->InternalizeOneByteString( | 3531 Handle<String> set_name = isolate->factory()->InternalizeOneByteString( |
| 3551 STATIC_ASCII_VECTOR("set_")); | 3532 STATIC_ASCII_VECTOR("set_")); |
| 3552 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name)); | 3533 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name)); |
| 3553 ASSERT(!isolate->has_pending_exception()); | 3534 ASSERT(!isolate->has_pending_exception()); |
| 3554 if (!setter->IsUndefined()) { | 3535 if (!setter->IsUndefined()) { |
| 3555 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 3536 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 3556 return receiver->SetPropertyWithDefinedSetter( | 3537 return SetPropertyWithDefinedSetter( |
| 3557 JSReceiver::cast(*setter), *value); | 3538 receiver, Handle<JSReceiver>::cast(setter), value); |
| 3558 } | 3539 } |
| 3559 | 3540 |
| 3560 if (strict_mode == kNonStrictMode) return *value; | 3541 if (strict_mode == kNonStrictMode) return value; |
| 3561 Handle<Object> args2[] = { name, proxy }; | 3542 Handle<Object> args2[] = { name, proxy }; |
| 3562 Handle<Object> error = isolate->factory()->NewTypeError( | 3543 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3563 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); | 3544 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); |
| 3564 return isolate->Throw(*error); | 3545 isolate->Throw(*error); |
| 3546 return Handle<Object>(); |
| 3565 } | 3547 } |
| 3566 | 3548 |
| 3567 | 3549 |
| 3568 Handle<Object> JSProxy::DeletePropertyWithHandler( | 3550 Handle<Object> JSProxy::DeletePropertyWithHandler( |
| 3569 Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) { | 3551 Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) { |
| 3570 Isolate* isolate = proxy->GetIsolate(); | 3552 Isolate* isolate = proxy->GetIsolate(); |
| 3571 | 3553 |
| 3572 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3554 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3573 if (name->IsSymbol()) return isolate->factory()->false_value(); | 3555 if (name->IsSymbol()) return isolate->factory()->false_value(); |
| 3574 | 3556 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3727 | 3709 |
| 3728 | 3710 |
| 3729 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { | 3711 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) { |
| 3730 CALL_HEAP_FUNCTION_VOID( | 3712 CALL_HEAP_FUNCTION_VOID( |
| 3731 object->GetIsolate(), | 3713 object->GetIsolate(), |
| 3732 object->AllocateStorageForMap(*map)); | 3714 object->AllocateStorageForMap(*map)); |
| 3733 } | 3715 } |
| 3734 | 3716 |
| 3735 | 3717 |
| 3736 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3718 void JSObject::MigrateInstance(Handle<JSObject> object) { |
| 3737 CALL_HEAP_FUNCTION_VOID( | 3719 // Converting any field to the most specific type will cause the |
| 3738 object->GetIsolate(), | 3720 // GeneralizeFieldRepresentation algorithm to create the most general existing |
| 3739 object->MigrateInstance()); | 3721 // transition that matches the object. This achieves what is needed. |
| 3722 Handle<Map> original_map(object->map()); |
| 3723 GeneralizeFieldRepresentation( |
| 3724 object, 0, Representation::None(), ALLOW_AS_CONSTANT); |
| 3725 if (FLAG_trace_migration) { |
| 3726 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
| 3727 } |
| 3740 } | 3728 } |
| 3741 | 3729 |
| 3742 | 3730 |
| 3743 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3731 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
| 3744 CALL_HEAP_FUNCTION( | 3732 MigrateInstance(object); |
| 3745 object->GetIsolate(), | 3733 return object; |
| 3746 object->MigrateInstance(), | |
| 3747 Object); | |
| 3748 } | 3734 } |
| 3749 | 3735 |
| 3750 | 3736 |
| 3751 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, | 3737 Handle<Object> JSObject::SetPropertyUsingTransition( |
| 3752 int modify_index, | 3738 Handle<JSObject> object, |
| 3753 Representation representation, | 3739 LookupResult* lookup, |
| 3754 StoreMode store_mode) { | 3740 Handle<Name> name, |
| 3755 CALL_HEAP_FUNCTION( | 3741 Handle<Object> value, |
| 3756 map->GetIsolate(), | 3742 PropertyAttributes attributes) { |
| 3757 map->GeneralizeRepresentation(modify_index, representation, store_mode), | 3743 Handle<Map> transition_map(lookup->GetTransitionTarget()); |
| 3758 Map); | |
| 3759 } | |
| 3760 | |
| 3761 | |
| 3762 static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, | |
| 3763 Handle<Name> name, | |
| 3764 Handle<Object> value, | |
| 3765 PropertyAttributes attributes) { | |
| 3766 Map* transition_map = lookup->GetTransitionTarget(); | |
| 3767 int descriptor = transition_map->LastAdded(); | 3744 int descriptor = transition_map->LastAdded(); |
| 3768 | 3745 |
| 3769 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3746 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3770 PropertyDetails details = descriptors->GetDetails(descriptor); | 3747 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3771 | 3748 |
| 3772 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3749 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3773 // AddProperty will either normalize the object, or create a new fast copy | 3750 // AddProperty will either normalize the object, or create a new fast copy |
| 3774 // of the map. If we get a fast copy of the map, all field representations | 3751 // of the map. If we get a fast copy of the map, all field representations |
| 3775 // will be tagged since the transition is omitted. | 3752 // will be tagged since the transition is omitted. |
| 3776 return lookup->holder()->AddProperty( | 3753 return JSObject::AddProperty( |
| 3777 *name, *value, attributes, kNonStrictMode, | 3754 object, name, value, attributes, kNonStrictMode, |
| 3778 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 3755 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
| 3779 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 3756 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
| 3780 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 3757 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
| 3781 } | 3758 } |
| 3782 | 3759 |
| 3783 // Keep the target CONSTANT if the same value is stored. | 3760 // Keep the target CONSTANT if the same value is stored. |
| 3784 // TODO(verwaest): Also support keeping the placeholder | 3761 // TODO(verwaest): Also support keeping the placeholder |
| 3785 // (value->IsUninitialized) as constant. | 3762 // (value->IsUninitialized) as constant. |
| 3786 if (details.type() == CONSTANT && | 3763 if (details.type() == CONSTANT && |
| 3787 descriptors->GetValue(descriptor) == *value) { | 3764 descriptors->GetValue(descriptor) == *value) { |
| 3788 lookup->holder()->set_map(transition_map); | 3765 object->set_map(*transition_map); |
| 3789 return *value; | 3766 return value; |
| 3790 } | 3767 } |
| 3791 | 3768 |
| 3792 Representation representation = details.representation(); | 3769 Representation representation = details.representation(); |
| 3793 | 3770 |
| 3794 if (!value->FitsRepresentation(representation) || | 3771 if (!value->FitsRepresentation(representation) || |
| 3795 details.type() == CONSTANT) { | 3772 details.type() == CONSTANT) { |
| 3796 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | 3773 transition_map = Map::GeneralizeRepresentation(transition_map, |
| 3797 descriptor, value->OptimalRepresentation(), FORCE_FIELD); | 3774 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
| 3798 if (!maybe_map->To(&transition_map)) return maybe_map; | |
| 3799 Object* back = transition_map->GetBackPointer(); | 3775 Object* back = transition_map->GetBackPointer(); |
| 3800 if (back->IsMap()) { | 3776 if (back->IsMap()) { |
| 3801 MaybeObject* maybe_failure = | 3777 MigrateToMap(object, handle(Map::cast(back))); |
| 3802 lookup->holder()->MigrateToMap(Map::cast(back)); | |
| 3803 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3804 } | 3778 } |
| 3805 descriptors = transition_map->instance_descriptors(); | 3779 descriptors = transition_map->instance_descriptors(); |
| 3806 representation = descriptors->GetDetails(descriptor).representation(); | 3780 representation = descriptors->GetDetails(descriptor).representation(); |
| 3807 } | 3781 } |
| 3808 | 3782 |
| 3809 int field_index = descriptors->GetFieldIndex(descriptor); | 3783 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3810 return lookup->holder()->AddFastPropertyUsingMap( | 3784 AddFastPropertyUsingMap( |
| 3811 transition_map, *name, *value, field_index, representation); | 3785 object, transition_map, name, value, field_index, representation); |
| 3786 return value; |
| 3812 } | 3787 } |
| 3813 | 3788 |
| 3814 | 3789 |
| 3815 static MaybeObject* SetPropertyToField(LookupResult* lookup, | 3790 static void SetPropertyToField(LookupResult* lookup, |
| 3816 Handle<Name> name, | 3791 Handle<Name> name, |
| 3817 Handle<Object> value) { | 3792 Handle<Object> value) { |
| 3818 Representation representation = lookup->representation(); | 3793 Representation representation = lookup->representation(); |
| 3819 if (!value->FitsRepresentation(representation) || | 3794 if (!value->FitsRepresentation(representation) || |
| 3820 lookup->type() == CONSTANT) { | 3795 lookup->type() == CONSTANT) { |
| 3821 MaybeObject* maybe_failure = | 3796 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), |
| 3822 lookup->holder()->GeneralizeFieldRepresentation( | 3797 lookup->GetDescriptorIndex(), |
| 3823 lookup->GetDescriptorIndex(), | 3798 value->OptimalRepresentation(), |
| 3824 value->OptimalRepresentation(), | 3799 FORCE_FIELD); |
| 3825 FORCE_FIELD); | |
| 3826 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3827 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 3800 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3828 int descriptor = lookup->GetDescriptorIndex(); | 3801 int descriptor = lookup->GetDescriptorIndex(); |
| 3829 representation = desc->GetDetails(descriptor).representation(); | 3802 representation = desc->GetDetails(descriptor).representation(); |
| 3830 } | 3803 } |
| 3831 | 3804 |
| 3832 if (FLAG_track_double_fields && representation.IsDouble()) { | 3805 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 3833 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 3806 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3834 lookup->GetFieldIndex().field_index())); | 3807 lookup->GetFieldIndex().field_index())); |
| 3835 storage->set_value(value->Number()); | 3808 storage->set_value(value->Number()); |
| 3836 return *value; | 3809 return; |
| 3837 } | 3810 } |
| 3838 | 3811 |
| 3839 lookup->holder()->FastPropertyAtPut( | 3812 lookup->holder()->FastPropertyAtPut( |
| 3840 lookup->GetFieldIndex().field_index(), *value); | 3813 lookup->GetFieldIndex().field_index(), *value); |
| 3841 return *value; | |
| 3842 } | 3814 } |
| 3843 | 3815 |
| 3844 | 3816 |
| 3845 static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup, | 3817 static void ConvertAndSetLocalProperty(LookupResult* lookup, |
| 3846 Name* name, | 3818 Handle<Name> name, |
| 3847 Object* value, | 3819 Handle<Object> value, |
| 3848 PropertyAttributes attributes) { | 3820 PropertyAttributes attributes) { |
| 3849 JSObject* object = lookup->holder(); | 3821 Handle<JSObject> object(lookup->holder()); |
| 3850 if (object->TooManyFastProperties()) { | 3822 if (object->TooManyFastProperties()) { |
| 3851 MaybeObject* maybe_failure = object->NormalizeProperties( | 3823 JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 3852 CLEAR_INOBJECT_PROPERTIES, 0); | |
| 3853 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3854 } | 3824 } |
| 3855 | 3825 |
| 3856 if (!object->HasFastProperties()) { | 3826 if (!object->HasFastProperties()) { |
| 3857 return object->ReplaceSlowProperty(name, value, attributes); | 3827 ReplaceSlowProperty(object, name, value, attributes); |
| 3828 return; |
| 3858 } | 3829 } |
| 3859 | 3830 |
| 3860 int descriptor_index = lookup->GetDescriptorIndex(); | 3831 int descriptor_index = lookup->GetDescriptorIndex(); |
| 3861 if (lookup->GetAttributes() == attributes) { | 3832 if (lookup->GetAttributes() == attributes) { |
| 3862 MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation( | 3833 JSObject::GeneralizeFieldRepresentation( |
| 3863 descriptor_index, Representation::Tagged(), FORCE_FIELD); | 3834 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); |
| 3864 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3865 } else { | 3835 } else { |
| 3866 Map* map; | 3836 Handle<Map> old_map(object->map()); |
| 3867 MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations( | 3837 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, |
| 3868 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | 3838 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
| 3869 if (!maybe_map->To(&map)) return maybe_map; | 3839 JSObject::MigrateToMap(object, new_map); |
| 3870 MaybeObject* maybe_failure = object->MigrateToMap(map); | |
| 3871 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3872 } | 3840 } |
| 3873 | 3841 |
| 3874 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 3842 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 3875 int index = descriptors->GetDetails(descriptor_index).field_index(); | 3843 int index = descriptors->GetDetails(descriptor_index).field_index(); |
| 3876 object->FastPropertyAtPut(index, value); | 3844 object->FastPropertyAtPut(index, *value); |
| 3877 return value; | |
| 3878 } | 3845 } |
| 3879 | 3846 |
| 3880 | 3847 |
| 3881 static MaybeObject* SetPropertyToFieldWithAttributes( | 3848 static void SetPropertyToFieldWithAttributes(LookupResult* lookup, |
| 3882 LookupResult* lookup, | 3849 Handle<Name> name, |
| 3883 Handle<Name> name, | 3850 Handle<Object> value, |
| 3884 Handle<Object> value, | 3851 PropertyAttributes attributes) { |
| 3885 PropertyAttributes attributes) { | |
| 3886 if (lookup->GetAttributes() == attributes) { | 3852 if (lookup->GetAttributes() == attributes) { |
| 3887 if (value->IsUninitialized()) return *value; | 3853 if (value->IsUninitialized()) return; |
| 3888 return SetPropertyToField(lookup, name, value); | 3854 SetPropertyToField(lookup, name, value); |
| 3889 } else { | 3855 } else { |
| 3890 return ConvertAndSetLocalProperty(lookup, *name, *value, attributes); | 3856 ConvertAndSetLocalProperty(lookup, name, value, attributes); |
| 3891 } | 3857 } |
| 3892 } | 3858 } |
| 3893 | 3859 |
| 3894 | 3860 |
| 3895 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, | 3861 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, |
| 3896 Name* name_raw, | 3862 LookupResult* lookup, |
| 3897 Object* value_raw, | 3863 Handle<Name> name, |
| 3898 PropertyAttributes attributes, | 3864 Handle<Object> value, |
| 3899 StrictModeFlag strict_mode, | 3865 PropertyAttributes attributes, |
| 3900 StoreFromKeyed store_mode) { | 3866 StrictModeFlag strict_mode, |
| 3901 Heap* heap = GetHeap(); | 3867 StoreFromKeyed store_mode) { |
| 3902 Isolate* isolate = heap->isolate(); | 3868 Isolate* isolate = object->GetIsolate(); |
| 3903 | 3869 |
| 3904 // Make sure that the top context does not change when doing callbacks or | 3870 // Make sure that the top context does not change when doing callbacks or |
| 3905 // interceptor calls. | 3871 // interceptor calls. |
| 3906 AssertNoContextChangeWithHandleScope ncc; | 3872 AssertNoContextChange ncc; |
| 3907 | 3873 |
| 3908 // Optimization for 2-byte strings often used as keys in a decompression | 3874 // Optimization for 2-byte strings often used as keys in a decompression |
| 3909 // dictionary. We internalize these short keys to avoid constantly | 3875 // dictionary. We internalize these short keys to avoid constantly |
| 3910 // reallocating them. | 3876 // reallocating them. |
| 3911 if (name_raw->IsString() && !name_raw->IsInternalizedString() && | 3877 if (name->IsString() && !name->IsInternalizedString() && |
| 3912 String::cast(name_raw)->length() <= 2) { | 3878 Handle<String>::cast(name)->length() <= 2) { |
| 3913 Object* internalized_version; | 3879 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); |
| 3914 { MaybeObject* maybe_string_version = | 3880 } |
| 3915 heap->InternalizeString(String::cast(name_raw)); | 3881 |
| 3916 if (maybe_string_version->ToObject(&internalized_version)) { | 3882 // Check access rights if needed. |
| 3917 name_raw = String::cast(internalized_version); | 3883 if (object->IsAccessCheckNeeded()) { |
| 3918 } | 3884 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 3885 return SetPropertyWithFailedAccessCheck(object, lookup, name, value, |
| 3886 true, strict_mode); |
| 3919 } | 3887 } |
| 3920 } | 3888 } |
| 3921 | 3889 |
| 3922 // Check access rights if needed. | 3890 if (object->IsJSGlobalProxy()) { |
| 3923 if (IsAccessCheckNeeded()) { | 3891 Handle<Object> proto(object->GetPrototype(), isolate); |
| 3924 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 3892 if (proto->IsNull()) return value; |
| 3925 return SetPropertyWithFailedAccessCheck( | 3893 ASSERT(proto->IsJSGlobalObject()); |
| 3926 lookup, name_raw, value_raw, true, strict_mode); | 3894 return SetPropertyForResult(Handle<JSObject>::cast(proto), |
| 3927 } | 3895 lookup, name, value, attributes, strict_mode, store_mode); |
| 3928 } | 3896 } |
| 3929 | 3897 |
| 3930 if (IsJSGlobalProxy()) { | 3898 ASSERT(!lookup->IsFound() || lookup->holder() == *object || |
| 3931 Object* proto = GetPrototype(); | |
| 3932 if (proto->IsNull()) return value_raw; | |
| 3933 ASSERT(proto->IsJSGlobalObject()); | |
| 3934 return JSObject::cast(proto)->SetPropertyForResult( | |
| 3935 lookup, name_raw, value_raw, attributes, strict_mode, store_mode); | |
| 3936 } | |
| 3937 | |
| 3938 ASSERT(!lookup->IsFound() || lookup->holder() == this || | |
| 3939 lookup->holder()->map()->is_hidden_prototype()); | 3899 lookup->holder()->map()->is_hidden_prototype()); |
| 3940 | 3900 |
| 3941 // From this point on everything needs to be handlified, because | 3901 if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) { |
| 3942 // SetPropertyViaPrototypes might call back into JavaScript. | |
| 3943 HandleScope scope(isolate); | |
| 3944 Handle<JSObject> self(this); | |
| 3945 Handle<Name> name(name_raw); | |
| 3946 Handle<Object> value(value_raw, isolate); | |
| 3947 | |
| 3948 if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) { | |
| 3949 bool done = false; | 3902 bool done = false; |
| 3950 MaybeObject* result_object = self->SetPropertyViaPrototypes( | 3903 Handle<Object> result_object = SetPropertyViaPrototypes( |
| 3951 *name, *value, attributes, strict_mode, &done); | 3904 object, name, value, attributes, strict_mode, &done); |
| 3952 if (done) return result_object; | 3905 if (done) return result_object; |
| 3953 } | 3906 } |
| 3954 | 3907 |
| 3955 if (!lookup->IsFound()) { | 3908 if (!lookup->IsFound()) { |
| 3956 // Neither properties nor transitions found. | 3909 // Neither properties nor transitions found. |
| 3957 return self->AddProperty( | 3910 return AddProperty( |
| 3958 *name, *value, attributes, strict_mode, store_mode); | 3911 object, name, value, attributes, strict_mode, store_mode); |
| 3959 } | 3912 } |
| 3960 | 3913 |
| 3961 if (lookup->IsProperty() && lookup->IsReadOnly()) { | 3914 if (lookup->IsProperty() && lookup->IsReadOnly()) { |
| 3962 if (strict_mode == kStrictMode) { | 3915 if (strict_mode == kStrictMode) { |
| 3963 Handle<Object> args[] = { name, self }; | 3916 Handle<Object> args[] = { name, object }; |
| 3964 return isolate->Throw(*isolate->factory()->NewTypeError( | 3917 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3965 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 3918 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3919 isolate->Throw(*error); |
| 3920 return Handle<Object>(); |
| 3966 } else { | 3921 } else { |
| 3967 return *value; | 3922 return value; |
| 3968 } | 3923 } |
| 3969 } | 3924 } |
| 3970 | 3925 |
| 3971 Handle<Object> old_value(heap->the_hole_value(), isolate); | 3926 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 3972 if (FLAG_harmony_observation && | 3927 if (FLAG_harmony_observation && |
| 3973 map()->is_observed() && lookup->IsDataProperty()) { | 3928 object->map()->is_observed() && lookup->IsDataProperty()) { |
| 3974 old_value = Object::GetProperty(self, name); | 3929 old_value = Object::GetProperty(object, name); |
| 3975 } | 3930 } |
| 3976 | 3931 |
| 3977 // This is a real property that is not read-only, or it is a | 3932 // This is a real property that is not read-only, or it is a |
| 3978 // transition or null descriptor and there are no setters in the prototypes. | 3933 // transition or null descriptor and there are no setters in the prototypes. |
| 3979 MaybeObject* result = *value; | 3934 Handle<Object> result = value; |
| 3980 switch (lookup->type()) { | 3935 switch (lookup->type()) { |
| 3981 case NORMAL: | 3936 case NORMAL: |
| 3982 result = lookup->holder()->SetNormalizedProperty(lookup, *value); | 3937 SetNormalizedProperty(handle(lookup->holder()), lookup, value); |
| 3983 break; | 3938 break; |
| 3984 case FIELD: | 3939 case FIELD: |
| 3985 result = SetPropertyToField(lookup, name, value); | 3940 SetPropertyToField(lookup, name, value); |
| 3986 break; | 3941 break; |
| 3987 case CONSTANT: | 3942 case CONSTANT: |
| 3988 // Only replace the constant if necessary. | 3943 // Only replace the constant if necessary. |
| 3989 if (*value == lookup->GetConstant()) return *value; | 3944 if (*value == lookup->GetConstant()) return value; |
| 3990 result = SetPropertyToField(lookup, name, value); | 3945 SetPropertyToField(lookup, name, value); |
| 3991 break; | 3946 break; |
| 3992 case CALLBACKS: { | 3947 case CALLBACKS: { |
| 3993 Object* callback_object = lookup->GetCallbackObject(); | 3948 Handle<Object> callback_object(lookup->GetCallbackObject(), isolate); |
| 3994 return self->SetPropertyWithCallback( | 3949 return SetPropertyWithCallback(object, callback_object, name, value, |
| 3995 callback_object, *name, *value, lookup->holder(), strict_mode); | 3950 handle(lookup->holder()), strict_mode); |
| 3996 } | 3951 } |
| 3997 case INTERCEPTOR: | 3952 case INTERCEPTOR: |
| 3998 result = lookup->holder()->SetPropertyWithInterceptor( | 3953 result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value, |
| 3999 *name, *value, attributes, strict_mode); | 3954 attributes, strict_mode); |
| 4000 break; | 3955 break; |
| 4001 case TRANSITION: { | 3956 case TRANSITION: |
| 4002 result = SetPropertyUsingTransition(lookup, name, value, attributes); | 3957 result = SetPropertyUsingTransition(handle(lookup->holder()), lookup, |
| 3958 name, value, attributes); |
| 4003 break; | 3959 break; |
| 4004 } | |
| 4005 case HANDLER: | 3960 case HANDLER: |
| 4006 case NONEXISTENT: | 3961 case NONEXISTENT: |
| 4007 UNREACHABLE(); | 3962 UNREACHABLE(); |
| 4008 } | 3963 } |
| 4009 | 3964 |
| 4010 Handle<Object> hresult; | 3965 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 4011 if (!result->ToHandle(&hresult, isolate)) return result; | |
| 4012 | 3966 |
| 4013 if (FLAG_harmony_observation && self->map()->is_observed()) { | 3967 if (FLAG_harmony_observation && object->map()->is_observed()) { |
| 4014 if (lookup->IsTransition()) { | 3968 if (lookup->IsTransition()) { |
| 4015 EnqueueChangeRecord(self, "new", name, old_value); | 3969 EnqueueChangeRecord(object, "new", name, old_value); |
| 4016 } else { | 3970 } else { |
| 4017 LookupResult new_lookup(isolate); | 3971 LookupResult new_lookup(isolate); |
| 4018 self->LocalLookup(*name, &new_lookup, true); | 3972 object->LocalLookup(*name, &new_lookup, true); |
| 4019 if (new_lookup.IsDataProperty()) { | 3973 if (new_lookup.IsDataProperty()) { |
| 4020 Handle<Object> new_value = Object::GetProperty(self, name); | 3974 Handle<Object> new_value = Object::GetProperty(object, name); |
| 4021 if (!new_value->SameValue(*old_value)) { | 3975 if (!new_value->SameValue(*old_value)) { |
| 4022 EnqueueChangeRecord(self, "updated", name, old_value); | 3976 EnqueueChangeRecord(object, "updated", name, old_value); |
| 4023 } | 3977 } |
| 4024 } | 3978 } |
| 4025 } | 3979 } |
| 4026 } | 3980 } |
| 4027 | 3981 |
| 4028 return *hresult; | 3982 return result; |
| 4029 } | 3983 } |
| 4030 | 3984 |
| 4031 | 3985 |
| 4032 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( | 3986 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline( |
| 4033 Name* key, | 3987 Name* key, |
| 4034 Object* value, | 3988 Object* value, |
| 4035 PropertyAttributes attributes, | 3989 PropertyAttributes attributes, |
| 4036 ValueType value_type, | 3990 ValueType value_type, |
| 4037 StoreMode mode, | 3991 StoreMode mode, |
| 4038 ExtensibilityCheck extensibility_check) { | 3992 ExtensibilityCheck extensibility_check) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4056 // present, add it with attributes NONE. This code is an exact clone of | 4010 // present, add it with attributes NONE. This code is an exact clone of |
| 4057 // SetProperty, with the check for IsReadOnly and the check for a | 4011 // SetProperty, with the check for IsReadOnly and the check for a |
| 4058 // callback setter removed. The two lines looking up the LookupResult | 4012 // callback setter removed. The two lines looking up the LookupResult |
| 4059 // result are also added. If one of the functions is changed, the other | 4013 // result are also added. If one of the functions is changed, the other |
| 4060 // should be. | 4014 // should be. |
| 4061 // Note that this method cannot be used to set the prototype of a function | 4015 // Note that this method cannot be used to set the prototype of a function |
| 4062 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" | 4016 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
| 4063 // doesn't handle function prototypes correctly. | 4017 // doesn't handle function prototypes correctly. |
| 4064 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( | 4018 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( |
| 4065 Handle<JSObject> object, | 4019 Handle<JSObject> object, |
| 4066 Handle<Name> key, | 4020 Handle<Name> name, |
| 4067 Handle<Object> value, | 4021 Handle<Object> value, |
| 4068 PropertyAttributes attributes, | 4022 PropertyAttributes attributes, |
| 4069 ValueType value_type, | 4023 ValueType value_type, |
| 4070 StoreMode mode, | 4024 StoreMode mode, |
| 4071 ExtensibilityCheck extensibility_check) { | 4025 ExtensibilityCheck extensibility_check) { |
| 4072 CALL_HEAP_FUNCTION( | 4026 Isolate* isolate = object->GetIsolate(); |
| 4073 object->GetIsolate(), | |
| 4074 object->SetLocalPropertyIgnoreAttributes( | |
| 4075 *key, *value, attributes, value_type, mode, extensibility_check), | |
| 4076 Object); | |
| 4077 } | |
| 4078 | 4027 |
| 4079 | |
| 4080 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | |
| 4081 Name* name_raw, | |
| 4082 Object* value_raw, | |
| 4083 PropertyAttributes attributes, | |
| 4084 ValueType value_type, | |
| 4085 StoreMode mode, | |
| 4086 ExtensibilityCheck extensibility_check) { | |
| 4087 // Make sure that the top context does not change when doing callbacks or | 4028 // Make sure that the top context does not change when doing callbacks or |
| 4088 // interceptor calls. | 4029 // interceptor calls. |
| 4089 AssertNoContextChangeWithHandleScope ncc; | 4030 AssertNoContextChange ncc; |
| 4090 Isolate* isolate = GetIsolate(); | 4031 |
| 4091 LookupResult lookup(isolate); | 4032 LookupResult lookup(isolate); |
| 4092 LocalLookup(name_raw, &lookup, true); | 4033 object->LocalLookup(*name, &lookup, true); |
| 4093 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup); | 4034 if (!lookup.IsFound()) { |
| 4035 object->map()->LookupTransition(*object, *name, &lookup); |
| 4036 } |
| 4037 |
| 4094 // Check access rights if needed. | 4038 // Check access rights if needed. |
| 4095 if (IsAccessCheckNeeded()) { | 4039 if (object->IsAccessCheckNeeded()) { |
| 4096 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 4040 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 4097 return SetPropertyWithFailedAccessCheck(&lookup, | 4041 return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, |
| 4098 name_raw, | 4042 false, kNonStrictMode); |
| 4099 value_raw, | |
| 4100 false, | |
| 4101 kNonStrictMode); | |
| 4102 } | 4043 } |
| 4103 } | 4044 } |
| 4104 | 4045 |
| 4105 if (IsJSGlobalProxy()) { | 4046 if (object->IsJSGlobalProxy()) { |
| 4106 Object* proto = GetPrototype(); | 4047 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4107 if (proto->IsNull()) return value_raw; | 4048 if (proto->IsNull()) return value; |
| 4108 ASSERT(proto->IsJSGlobalObject()); | 4049 ASSERT(proto->IsJSGlobalObject()); |
| 4109 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( | 4050 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), |
| 4110 name_raw, | 4051 name, value, attributes, value_type, mode, extensibility_check); |
| 4111 value_raw, | |
| 4112 attributes, | |
| 4113 value_type, | |
| 4114 mode, | |
| 4115 extensibility_check); | |
| 4116 } | 4052 } |
| 4117 | 4053 |
| 4118 if (lookup.IsFound() && | 4054 if (lookup.IsFound() && |
| 4119 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { | 4055 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { |
| 4120 LocalLookupRealNamedProperty(name_raw, &lookup); | 4056 object->LocalLookupRealNamedProperty(*name, &lookup); |
| 4121 } | 4057 } |
| 4122 | 4058 |
| 4123 // Check for accessor in prototype chain removed here in clone. | 4059 // Check for accessor in prototype chain removed here in clone. |
| 4124 if (!lookup.IsFound()) { | 4060 if (!lookup.IsFound()) { |
| 4125 // Neither properties nor transitions found. | 4061 // Neither properties nor transitions found. |
| 4126 return AddProperty( | 4062 return AddProperty(object, name, value, attributes, kNonStrictMode, |
| 4127 name_raw, value_raw, attributes, kNonStrictMode, | |
| 4128 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); | 4063 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); |
| 4129 } | 4064 } |
| 4130 | 4065 |
| 4131 // From this point on everything needs to be handlified. | 4066 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 4132 HandleScope scope(isolate); | |
| 4133 Handle<JSObject> self(this); | |
| 4134 Handle<Name> name(name_raw); | |
| 4135 Handle<Object> value(value_raw, isolate); | |
| 4136 | |
| 4137 Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate); | |
| 4138 PropertyAttributes old_attributes = ABSENT; | 4067 PropertyAttributes old_attributes = ABSENT; |
| 4139 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 4068 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
| 4140 if (is_observed && lookup.IsProperty()) { | 4069 if (is_observed && lookup.IsProperty()) { |
| 4141 if (lookup.IsDataProperty()) old_value = | 4070 if (lookup.IsDataProperty()) old_value = |
| 4142 Object::GetProperty(self, name); | 4071 Object::GetProperty(object, name); |
| 4143 old_attributes = lookup.GetAttributes(); | 4072 old_attributes = lookup.GetAttributes(); |
| 4144 } | 4073 } |
| 4145 | 4074 |
| 4146 // Check of IsReadOnly removed from here in clone. | 4075 // Check of IsReadOnly removed from here in clone. |
| 4147 MaybeObject* result = *value; | |
| 4148 switch (lookup.type()) { | 4076 switch (lookup.type()) { |
| 4149 case NORMAL: | 4077 case NORMAL: |
| 4150 result = self->ReplaceSlowProperty(*name, *value, attributes); | 4078 ReplaceSlowProperty(object, name, value, attributes); |
| 4151 break; | 4079 break; |
| 4152 case FIELD: | 4080 case FIELD: |
| 4153 result = SetPropertyToFieldWithAttributes( | 4081 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |
| 4154 &lookup, name, value, attributes); | |
| 4155 break; | 4082 break; |
| 4156 case CONSTANT: | 4083 case CONSTANT: |
| 4157 // Only replace the constant if necessary. | 4084 // Only replace the constant if necessary. |
| 4158 if (lookup.GetAttributes() != attributes || | 4085 if (lookup.GetAttributes() != attributes || |
| 4159 *value != lookup.GetConstant()) { | 4086 *value != lookup.GetConstant()) { |
| 4160 result = SetPropertyToFieldWithAttributes( | 4087 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |
| 4161 &lookup, name, value, attributes); | |
| 4162 } | 4088 } |
| 4163 break; | 4089 break; |
| 4164 case CALLBACKS: | 4090 case CALLBACKS: |
| 4165 result = ConvertAndSetLocalProperty(&lookup, *name, *value, attributes); | 4091 ConvertAndSetLocalProperty(&lookup, name, value, attributes); |
| 4166 break; | 4092 break; |
| 4167 case TRANSITION: | 4093 case TRANSITION: { |
| 4168 result = SetPropertyUsingTransition(&lookup, name, value, attributes); | 4094 Handle<Object> result = SetPropertyUsingTransition( |
| 4095 handle(lookup.holder()), &lookup, name, value, attributes); |
| 4096 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 4169 break; | 4097 break; |
| 4098 } |
| 4170 case NONEXISTENT: | 4099 case NONEXISTENT: |
| 4171 case HANDLER: | 4100 case HANDLER: |
| 4172 case INTERCEPTOR: | 4101 case INTERCEPTOR: |
| 4173 UNREACHABLE(); | 4102 UNREACHABLE(); |
| 4174 } | 4103 } |
| 4175 | 4104 |
| 4176 Handle<Object> hresult; | |
| 4177 if (!result->ToHandle(&hresult, isolate)) return result; | |
| 4178 | |
| 4179 if (is_observed) { | 4105 if (is_observed) { |
| 4180 if (lookup.IsTransition()) { | 4106 if (lookup.IsTransition()) { |
| 4181 EnqueueChangeRecord(self, "new", name, old_value); | 4107 EnqueueChangeRecord(object, "new", name, old_value); |
| 4182 } else if (old_value->IsTheHole()) { | 4108 } else if (old_value->IsTheHole()) { |
| 4183 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 4109 EnqueueChangeRecord(object, "reconfigured", name, old_value); |
| 4184 } else { | 4110 } else { |
| 4185 LookupResult new_lookup(isolate); | 4111 LookupResult new_lookup(isolate); |
| 4186 self->LocalLookup(*name, &new_lookup, true); | 4112 object->LocalLookup(*name, &new_lookup, true); |
| 4187 bool value_changed = false; | 4113 bool value_changed = false; |
| 4188 if (new_lookup.IsDataProperty()) { | 4114 if (new_lookup.IsDataProperty()) { |
| 4189 Handle<Object> new_value = Object::GetProperty(self, name); | 4115 Handle<Object> new_value = Object::GetProperty(object, name); |
| 4190 value_changed = !old_value->SameValue(*new_value); | 4116 value_changed = !old_value->SameValue(*new_value); |
| 4191 } | 4117 } |
| 4192 if (new_lookup.GetAttributes() != old_attributes) { | 4118 if (new_lookup.GetAttributes() != old_attributes) { |
| 4193 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 4119 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
| 4194 EnqueueChangeRecord(self, "reconfigured", name, old_value); | 4120 EnqueueChangeRecord(object, "reconfigured", name, old_value); |
| 4195 } else if (value_changed) { | 4121 } else if (value_changed) { |
| 4196 EnqueueChangeRecord(self, "updated", name, old_value); | 4122 EnqueueChangeRecord(object, "updated", name, old_value); |
| 4197 } | 4123 } |
| 4198 } | 4124 } |
| 4199 } | 4125 } |
| 4200 | 4126 |
| 4201 return *hresult; | 4127 return value; |
| 4202 } | 4128 } |
| 4203 | 4129 |
| 4204 | 4130 |
| 4205 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 4131 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
| 4206 JSObject* receiver, | 4132 JSObject* receiver, |
| 4207 Name* name, | 4133 Name* name, |
| 4208 bool continue_search) { | 4134 bool continue_search) { |
| 4209 // Check local property, ignore interceptor. | 4135 // Check local property, ignore interceptor. |
| 4210 LookupResult result(GetIsolate()); | 4136 LookupResult result(GetIsolate()); |
| 4211 LocalLookupRealNamedProperty(name, &result); | 4137 LocalLookupRealNamedProperty(name, &result); |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4660 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); | 4586 PropertyDetails details = PropertyDetails(NONE, NORMAL, 0); |
| 4661 MaybeObject* maybe_result = | 4587 MaybeObject* maybe_result = |
| 4662 dictionary->AddNumberEntry(i, value, details); | 4588 dictionary->AddNumberEntry(i, value, details); |
| 4663 if (!maybe_result->To(&dictionary)) return maybe_result; | 4589 if (!maybe_result->To(&dictionary)) return maybe_result; |
| 4664 } | 4590 } |
| 4665 } | 4591 } |
| 4666 return dictionary; | 4592 return dictionary; |
| 4667 } | 4593 } |
| 4668 | 4594 |
| 4669 | 4595 |
| 4596 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( |
| 4597 Handle<FixedArrayBase> array, |
| 4598 int length, |
| 4599 Handle<SeededNumberDictionary> dict) { |
| 4600 Isolate* isolate = array->GetIsolate(); |
| 4601 CALL_HEAP_FUNCTION(isolate, |
| 4602 CopyFastElementsToDictionary( |
| 4603 isolate, *array, length, *dict), |
| 4604 SeededNumberDictionary); |
| 4605 } |
| 4606 |
| 4607 |
| 4670 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4608 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
| 4671 Handle<JSObject> object) { | 4609 Handle<JSObject> object) { |
| 4672 CALL_HEAP_FUNCTION(object->GetIsolate(), | 4610 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 4673 object->NormalizeElements(), | 4611 object->NormalizeElements(), |
| 4674 SeededNumberDictionary); | 4612 SeededNumberDictionary); |
| 4675 } | 4613 } |
| 4676 | 4614 |
| 4677 | 4615 |
| 4678 MaybeObject* JSObject::NormalizeElements() { | 4616 MaybeObject* JSObject::NormalizeElements() { |
| 4679 ASSERT(!HasExternalArrayElements()); | 4617 ASSERT(!HasExternalArrayElements()); |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5145 if (object->IsJSGlobalProxy()) { | 5083 if (object->IsJSGlobalProxy()) { |
| 5146 Handle<Object> proto(object->GetPrototype(), isolate); | 5084 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5147 if (proto->IsNull()) return factory->false_value(); | 5085 if (proto->IsNull()) return factory->false_value(); |
| 5148 ASSERT(proto->IsJSGlobalObject()); | 5086 ASSERT(proto->IsJSGlobalObject()); |
| 5149 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); | 5087 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); |
| 5150 } | 5088 } |
| 5151 | 5089 |
| 5152 Handle<Object> old_value; | 5090 Handle<Object> old_value; |
| 5153 bool should_enqueue_change_record = false; | 5091 bool should_enqueue_change_record = false; |
| 5154 if (FLAG_harmony_observation && object->map()->is_observed()) { | 5092 if (FLAG_harmony_observation && object->map()->is_observed()) { |
| 5155 should_enqueue_change_record = object->HasLocalElement(index); | 5093 should_enqueue_change_record = HasLocalElement(object, index); |
| 5156 if (should_enqueue_change_record) { | 5094 if (should_enqueue_change_record) { |
| 5157 old_value = object->GetLocalElementAccessorPair(index) != NULL | 5095 old_value = object->GetLocalElementAccessorPair(index) != NULL |
| 5158 ? Handle<Object>::cast(factory->the_hole_value()) | 5096 ? Handle<Object>::cast(factory->the_hole_value()) |
| 5159 : Object::GetElement(isolate, object, index); | 5097 : Object::GetElement(isolate, object, index); |
| 5160 } | 5098 } |
| 5161 } | 5099 } |
| 5162 | 5100 |
| 5163 // Skip interceptor if forcing deletion. | 5101 // Skip interceptor if forcing deletion. |
| 5164 Handle<Object> result; | 5102 Handle<Object> result; |
| 5165 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { | 5103 if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) { |
| 5166 result = DeleteElementWithInterceptor(object, index); | 5104 result = DeleteElementWithInterceptor(object, index); |
| 5167 } else { | 5105 } else { |
| 5168 result = AccessorDelete(object, index, mode); | 5106 result = AccessorDelete(object, index, mode); |
| 5169 } | 5107 } |
| 5170 | 5108 |
| 5171 if (should_enqueue_change_record && !object->HasLocalElement(index)) { | 5109 if (should_enqueue_change_record && !HasLocalElement(object, index)) { |
| 5172 Handle<String> name = factory->Uint32ToString(index); | 5110 Handle<String> name = factory->Uint32ToString(index); |
| 5173 EnqueueChangeRecord(object, "deleted", name, old_value); | 5111 EnqueueChangeRecord(object, "deleted", name, old_value); |
| 5174 } | 5112 } |
| 5175 | 5113 |
| 5176 return result; | 5114 return result; |
| 5177 } | 5115 } |
| 5178 | 5116 |
| 5179 | 5117 |
| 5180 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5118 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
| 5181 Handle<Name> name, | 5119 Handle<Name> name, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5236 } else { | 5174 } else { |
| 5237 result = DeletePropertyWithInterceptor(object, name); | 5175 result = DeletePropertyWithInterceptor(object, name); |
| 5238 } | 5176 } |
| 5239 } else { | 5177 } else { |
| 5240 // Normalize object if needed. | 5178 // Normalize object if needed. |
| 5241 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5179 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 5242 // Make sure the properties are normalized before removing the entry. | 5180 // Make sure the properties are normalized before removing the entry. |
| 5243 result = DeleteNormalizedProperty(object, name, mode); | 5181 result = DeleteNormalizedProperty(object, name, mode); |
| 5244 } | 5182 } |
| 5245 | 5183 |
| 5246 if (is_observed && !object->HasLocalProperty(*name)) { | 5184 if (is_observed && !HasLocalProperty(object, name)) { |
| 5247 EnqueueChangeRecord(object, "deleted", name, old_value); | 5185 EnqueueChangeRecord(object, "deleted", name, old_value); |
| 5248 } | 5186 } |
| 5249 | 5187 |
| 5250 return result; | 5188 return result; |
| 5251 } | 5189 } |
| 5252 | 5190 |
| 5253 | 5191 |
| 5254 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, | 5192 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object, |
| 5255 uint32_t index, | 5193 uint32_t index, |
| 5256 DeleteMode mode) { | 5194 DeleteMode mode) { |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5475 attrs |= READ_ONLY; | 5413 attrs |= READ_ONLY; |
| 5476 } | 5414 } |
| 5477 details = details.CopyAddAttributes( | 5415 details = details.CopyAddAttributes( |
| 5478 static_cast<PropertyAttributes>(attrs)); | 5416 static_cast<PropertyAttributes>(attrs)); |
| 5479 dictionary->DetailsAtPut(i, details); | 5417 dictionary->DetailsAtPut(i, details); |
| 5480 } | 5418 } |
| 5481 } | 5419 } |
| 5482 } | 5420 } |
| 5483 | 5421 |
| 5484 | 5422 |
| 5485 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) { | 5423 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { |
| 5486 // Freezing non-strict arguments should be handled elsewhere. | 5424 // Freezing non-strict arguments should be handled elsewhere. |
| 5487 ASSERT(!HasNonStrictArgumentsElements()); | 5425 ASSERT(!object->HasNonStrictArgumentsElements()); |
| 5488 | 5426 |
| 5489 Heap* heap = isolate->heap(); | 5427 if (object->map()->is_frozen()) return object; |
| 5490 | 5428 |
| 5491 if (map()->is_frozen()) return this; | 5429 Isolate* isolate = object->GetIsolate(); |
| 5492 | 5430 if (object->IsAccessCheckNeeded() && |
| 5493 if (IsAccessCheckNeeded() && | 5431 !isolate->MayNamedAccess(*object, |
| 5494 !isolate->MayNamedAccess(this, | 5432 isolate->heap()->undefined_value(), |
| 5495 heap->undefined_value(), | |
| 5496 v8::ACCESS_KEYS)) { | 5433 v8::ACCESS_KEYS)) { |
| 5497 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); | 5434 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); |
| 5498 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5435 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5499 return heap->false_value(); | 5436 return isolate->factory()->false_value(); |
| 5500 } | 5437 } |
| 5501 | 5438 |
| 5502 if (IsJSGlobalProxy()) { | 5439 if (object->IsJSGlobalProxy()) { |
| 5503 Object* proto = GetPrototype(); | 5440 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5504 if (proto->IsNull()) return this; | 5441 if (proto->IsNull()) return object; |
| 5505 ASSERT(proto->IsJSGlobalObject()); | 5442 ASSERT(proto->IsJSGlobalObject()); |
| 5506 return JSObject::cast(proto)->Freeze(isolate); | 5443 return Freeze(Handle<JSObject>::cast(proto)); |
| 5507 } | 5444 } |
| 5508 | 5445 |
| 5509 // It's not possible to freeze objects with external array elements | 5446 // It's not possible to freeze objects with external array elements |
| 5510 if (HasExternalArrayElements()) { | 5447 if (object->HasExternalArrayElements()) { |
| 5511 HandleScope scope(isolate); | |
| 5512 Handle<Object> object(this, isolate); | |
| 5513 Handle<Object> error = | 5448 Handle<Object> error = |
| 5514 isolate->factory()->NewTypeError( | 5449 isolate->factory()->NewTypeError( |
| 5515 "cant_prevent_ext_external_array_elements", | 5450 "cant_prevent_ext_external_array_elements", |
| 5516 HandleVector(&object, 1)); | 5451 HandleVector(&object, 1)); |
| 5517 return isolate->Throw(*error); | 5452 isolate->Throw(*error); |
| 5453 return Handle<Object>(); |
| 5518 } | 5454 } |
| 5519 | 5455 |
| 5520 SeededNumberDictionary* new_element_dictionary = NULL; | 5456 Handle<SeededNumberDictionary> new_element_dictionary; |
| 5521 if (!elements()->IsDictionary()) { | 5457 if (!object->elements()->IsDictionary()) { |
| 5522 int length = IsJSArray() | 5458 int length = object->IsJSArray() |
| 5523 ? Smi::cast(JSArray::cast(this)->length())->value() | 5459 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
| 5524 : elements()->length(); | 5460 : object->elements()->length(); |
| 5525 if (length > 0) { | 5461 if (length > 0) { |
| 5526 int capacity = 0; | 5462 int capacity = 0; |
| 5527 int used = 0; | 5463 int used = 0; |
| 5528 GetElementsCapacityAndUsage(&capacity, &used); | 5464 object->GetElementsCapacityAndUsage(&capacity, &used); |
| 5529 MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used); | 5465 new_element_dictionary = |
| 5530 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | 5466 isolate->factory()->NewSeededNumberDictionary(used); |
| 5531 | 5467 |
| 5532 // Move elements to a dictionary; avoid calling NormalizeElements to avoid | 5468 // Move elements to a dictionary; avoid calling NormalizeElements to avoid |
| 5533 // unnecessary transitions. | 5469 // unnecessary transitions. |
| 5534 maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length, | 5470 new_element_dictionary = CopyFastElementsToDictionary( |
| 5535 new_element_dictionary); | 5471 handle(object->elements()), length, new_element_dictionary); |
| 5536 if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict; | |
| 5537 } else { | 5472 } else { |
| 5538 // No existing elements, use a pre-allocated empty backing store | 5473 // No existing elements, use a pre-allocated empty backing store |
| 5539 new_element_dictionary = heap->empty_slow_element_dictionary(); | 5474 new_element_dictionary = |
| 5475 isolate->factory()->empty_slow_element_dictionary(); |
| 5540 } | 5476 } |
| 5541 } | 5477 } |
| 5542 | 5478 |
| 5543 LookupResult result(isolate); | 5479 LookupResult result(isolate); |
| 5544 map()->LookupTransition(this, heap->frozen_symbol(), &result); | 5480 Handle<Map> old_map(object->map()); |
| 5481 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result); |
| 5545 if (result.IsTransition()) { | 5482 if (result.IsTransition()) { |
| 5546 Map* transition_map = result.GetTransitionTarget(); | 5483 Map* transition_map = result.GetTransitionTarget(); |
| 5547 ASSERT(transition_map->has_dictionary_elements()); | 5484 ASSERT(transition_map->has_dictionary_elements()); |
| 5548 ASSERT(transition_map->is_frozen()); | 5485 ASSERT(transition_map->is_frozen()); |
| 5549 ASSERT(!transition_map->is_extensible()); | 5486 ASSERT(!transition_map->is_extensible()); |
| 5550 set_map(transition_map); | 5487 object->set_map(transition_map); |
| 5551 } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) { | 5488 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
| 5552 // Create a new descriptor array with fully-frozen properties | 5489 // Create a new descriptor array with fully-frozen properties |
| 5553 int num_descriptors = map()->NumberOfOwnDescriptors(); | 5490 int num_descriptors = old_map->NumberOfOwnDescriptors(); |
| 5554 DescriptorArray* new_descriptors; | 5491 Handle<DescriptorArray> new_descriptors = |
| 5555 MaybeObject* maybe_descriptors = | 5492 DescriptorArray::CopyUpToAddAttributes( |
| 5556 map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors, | 5493 handle(old_map->instance_descriptors()), num_descriptors, FROZEN); |
| 5557 FROZEN); | 5494 Handle<Map> new_map = Map::CopyReplaceDescriptors( |
| 5558 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5495 old_map, new_descriptors, INSERT_TRANSITION, |
| 5559 | 5496 isolate->factory()->frozen_symbol()); |
| 5560 Map* new_map; | |
| 5561 MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors( | |
| 5562 new_descriptors, INSERT_TRANSITION, heap->frozen_symbol()); | |
| 5563 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 5564 new_map->freeze(); | 5497 new_map->freeze(); |
| 5565 new_map->set_is_extensible(false); | 5498 new_map->set_is_extensible(false); |
| 5566 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5499 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5567 set_map(new_map); | 5500 object->set_map(*new_map); |
| 5568 } else { | 5501 } else { |
| 5569 // Slow path: need to normalize properties for safety | 5502 // Slow path: need to normalize properties for safety |
| 5570 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 5503 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 5571 if (maybe->IsFailure()) return maybe; | |
| 5572 | 5504 |
| 5573 // Create a new map, since other objects with this map may be extensible. | 5505 // Create a new map, since other objects with this map may be extensible. |
| 5574 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5506 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5575 Map* new_map; | 5507 Handle<Map> new_map = Map::Copy(handle(object->map())); |
| 5576 MaybeObject* maybe_copy = map()->Copy(); | |
| 5577 if (!maybe_copy->To(&new_map)) return maybe_copy; | |
| 5578 new_map->freeze(); | 5508 new_map->freeze(); |
| 5579 new_map->set_is_extensible(false); | 5509 new_map->set_is_extensible(false); |
| 5580 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5510 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5581 set_map(new_map); | 5511 object->set_map(*new_map); |
| 5582 | 5512 |
| 5583 // Freeze dictionary-mode properties | 5513 // Freeze dictionary-mode properties |
| 5584 FreezeDictionary(property_dictionary()); | 5514 FreezeDictionary(object->property_dictionary()); |
| 5585 } | 5515 } |
| 5586 | 5516 |
| 5587 ASSERT(map()->has_dictionary_elements()); | 5517 ASSERT(object->map()->has_dictionary_elements()); |
| 5588 if (new_element_dictionary != NULL) { | 5518 if (!new_element_dictionary.is_null()) { |
| 5589 set_elements(new_element_dictionary); | 5519 object->set_elements(*new_element_dictionary); |
| 5590 } | 5520 } |
| 5591 | 5521 |
| 5592 if (elements() != heap->empty_slow_element_dictionary()) { | 5522 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
| 5593 SeededNumberDictionary* dictionary = element_dictionary(); | 5523 SeededNumberDictionary* dictionary = object->element_dictionary(); |
| 5594 // Make sure we never go back to the fast case | 5524 // Make sure we never go back to the fast case |
| 5595 dictionary->set_requires_slow_elements(); | 5525 dictionary->set_requires_slow_elements(); |
| 5596 // Freeze all elements in the dictionary | 5526 // Freeze all elements in the dictionary |
| 5597 FreezeDictionary(dictionary); | 5527 FreezeDictionary(dictionary); |
| 5598 } | 5528 } |
| 5599 | 5529 |
| 5600 return this; | 5530 return object; |
| 5601 } | 5531 } |
| 5602 | 5532 |
| 5603 | 5533 |
| 5604 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { | 5534 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) { |
| 5605 if (map()->is_observed()) | 5535 if (map()->is_observed()) |
| 5606 return isolate->heap()->undefined_value(); | 5536 return isolate->heap()->undefined_value(); |
| 5607 | 5537 |
| 5608 Heap* heap = isolate->heap(); | 5538 Heap* heap = isolate->heap(); |
| 5609 | 5539 |
| 5610 if (!HasExternalArrayElements()) { | 5540 if (!HasExternalArrayElements()) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5628 MaybeObject* maybe_copy = map()->Copy(); | 5558 MaybeObject* maybe_copy = map()->Copy(); |
| 5629 if (!maybe_copy->To(&new_map)) return maybe_copy; | 5559 if (!maybe_copy->To(&new_map)) return maybe_copy; |
| 5630 new_map->set_is_observed(true); | 5560 new_map->set_is_observed(true); |
| 5631 } | 5561 } |
| 5632 set_map(new_map); | 5562 set_map(new_map); |
| 5633 | 5563 |
| 5634 return heap->undefined_value(); | 5564 return heap->undefined_value(); |
| 5635 } | 5565 } |
| 5636 | 5566 |
| 5637 | 5567 |
| 5638 // TODO(mstarzinger): Temporary wrapper until handlified. | |
| 5639 static Handle<Object> NewStorageFor(Isolate* isolate, | |
| 5640 Handle<Object> object, | |
| 5641 Representation representation) { | |
| 5642 Heap* heap = isolate->heap(); | |
| 5643 CALL_HEAP_FUNCTION(isolate, | |
| 5644 object->AllocateNewStorageFor(heap, representation), | |
| 5645 Object); | |
| 5646 } | |
| 5647 | |
| 5648 | |
| 5649 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { | 5568 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
| 5650 Isolate* isolate = object->GetIsolate(); | 5569 Isolate* isolate = object->GetIsolate(); |
| 5651 CALL_HEAP_FUNCTION(isolate, | 5570 CALL_HEAP_FUNCTION(isolate, |
| 5652 isolate->heap()->CopyJSObject(*object), JSObject); | 5571 isolate->heap()->CopyJSObject(*object), JSObject); |
| 5653 } | 5572 } |
| 5654 | 5573 |
| 5655 | 5574 |
| 5656 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { | 5575 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { |
| 5657 Isolate* isolate = object->GetIsolate(); | 5576 Isolate* isolate = object->GetIsolate(); |
| 5658 StackLimitCheck check(isolate); | 5577 StackLimitCheck check(isolate); |
| 5659 if (check.HasOverflowed()) { | 5578 if (check.HasOverflowed()) { |
| 5660 isolate->StackOverflow(); | 5579 isolate->StackOverflow(); |
| 5661 return Handle<JSObject>::null(); | 5580 return Handle<JSObject>::null(); |
| 5662 } | 5581 } |
| 5663 | 5582 |
| 5664 if (object->map()->is_deprecated()) { | 5583 if (object->map()->is_deprecated()) { |
| 5665 MigrateInstance(object); | 5584 MigrateInstance(object); |
| 5666 } | 5585 } |
| 5667 | 5586 |
| 5668 Handle<JSObject> copy = Copy(object); | 5587 Handle<JSObject> copy = Copy(object); |
| 5669 | 5588 |
| 5589 HandleScope scope(isolate); |
| 5590 |
| 5670 // Deep copy local properties. | 5591 // Deep copy local properties. |
| 5671 if (copy->HasFastProperties()) { | 5592 if (copy->HasFastProperties()) { |
| 5672 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); | 5593 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); |
| 5673 int limit = copy->map()->NumberOfOwnDescriptors(); | 5594 int limit = copy->map()->NumberOfOwnDescriptors(); |
| 5674 for (int i = 0; i < limit; i++) { | 5595 for (int i = 0; i < limit; i++) { |
| 5675 PropertyDetails details = descriptors->GetDetails(i); | 5596 PropertyDetails details = descriptors->GetDetails(i); |
| 5676 if (details.type() != FIELD) continue; | 5597 if (details.type() != FIELD) continue; |
| 5677 int index = descriptors->GetFieldIndex(i); | 5598 int index = descriptors->GetFieldIndex(i); |
| 5678 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 5599 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
| 5679 if (value->IsJSObject()) { | 5600 if (value->IsJSObject()) { |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6187 if (!object->CanSetCallback(*name)) return; | 6108 if (!object->CanSetCallback(*name)) return; |
| 6188 | 6109 |
| 6189 uint32_t index = 0; | 6110 uint32_t index = 0; |
| 6190 bool is_element = name->AsArrayIndex(&index); | 6111 bool is_element = name->AsArrayIndex(&index); |
| 6191 | 6112 |
| 6192 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6113 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6193 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); | 6114 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
| 6194 bool preexists = false; | 6115 bool preexists = false; |
| 6195 if (is_observed) { | 6116 if (is_observed) { |
| 6196 if (is_element) { | 6117 if (is_element) { |
| 6197 preexists = object->HasLocalElement(index); | 6118 preexists = HasLocalElement(object, index); |
| 6198 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { | 6119 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
| 6199 old_value = Object::GetElement(isolate, object, index); | 6120 old_value = Object::GetElement(isolate, object, index); |
| 6200 } | 6121 } |
| 6201 } else { | 6122 } else { |
| 6202 LookupResult lookup(isolate); | 6123 LookupResult lookup(isolate); |
| 6203 object->LocalLookup(*name, &lookup, true); | 6124 object->LocalLookup(*name, &lookup, true); |
| 6204 preexists = lookup.IsProperty(); | 6125 preexists = lookup.IsProperty(); |
| 6205 if (preexists && lookup.IsDataProperty()) { | 6126 if (preexists && lookup.IsDataProperty()) { |
| 6206 old_value = Object::GetProperty(object, name); | 6127 old_value = Object::GetProperty(object, name); |
| 6207 } | 6128 } |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6657 result->InitializeDescriptors(new_descriptors); | 6578 result->InitializeDescriptors(new_descriptors); |
| 6658 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 6579 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
| 6659 | 6580 |
| 6660 set_transitions(transitions); | 6581 set_transitions(transitions); |
| 6661 set_owns_descriptors(false); | 6582 set_owns_descriptors(false); |
| 6662 | 6583 |
| 6663 return result; | 6584 return result; |
| 6664 } | 6585 } |
| 6665 | 6586 |
| 6666 | 6587 |
| 6588 Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
| 6589 Handle<DescriptorArray> descriptors, |
| 6590 TransitionFlag flag, |
| 6591 Handle<Name> name) { |
| 6592 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6593 map->CopyReplaceDescriptors(*descriptors, flag, *name), |
| 6594 Map); |
| 6595 } |
| 6596 |
| 6597 |
| 6667 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 6598 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
| 6668 TransitionFlag flag, | 6599 TransitionFlag flag, |
| 6669 Name* name, | 6600 Name* name, |
| 6670 SimpleTransitionFlag simple_flag) { | 6601 SimpleTransitionFlag simple_flag) { |
| 6671 ASSERT(descriptors->IsSortedNoDuplicates()); | 6602 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6672 | 6603 |
| 6673 Map* result; | 6604 Map* result; |
| 6674 MaybeObject* maybe_result = CopyDropDescriptors(); | 6605 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 6675 if (!maybe_result->To(&result)) return maybe_result; | 6606 if (!maybe_result->To(&result)) return maybe_result; |
| 6676 | 6607 |
| 6677 result->InitializeDescriptors(descriptors); | 6608 result->InitializeDescriptors(descriptors); |
| 6678 | 6609 |
| 6679 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6610 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
| 6680 TransitionArray* transitions; | 6611 TransitionArray* transitions; |
| 6681 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6612 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
| 6682 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6613 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 6683 set_transitions(transitions); | 6614 set_transitions(transitions); |
| 6684 result->SetBackPointer(this); | 6615 result->SetBackPointer(this); |
| 6685 } else { | 6616 } else { |
| 6686 descriptors->InitializeRepresentations(Representation::Tagged()); | 6617 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 6687 } | 6618 } |
| 6688 | 6619 |
| 6689 return result; | 6620 return result; |
| 6690 } | 6621 } |
| 6691 | 6622 |
| 6692 | 6623 |
| 6624 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 6625 int new_descriptor, |
| 6626 Handle<DescriptorArray> descriptors) { |
| 6627 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6628 map->CopyInstallDescriptors(new_descriptor, *descriptors), |
| 6629 Map); |
| 6630 } |
| 6631 |
| 6632 |
| 6693 // Since this method is used to rewrite an existing transition tree, it can | 6633 // Since this method is used to rewrite an existing transition tree, it can |
| 6694 // always insert transitions without checking. | 6634 // always insert transitions without checking. |
| 6695 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6635 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, |
| 6696 DescriptorArray* descriptors) { | 6636 DescriptorArray* descriptors) { |
| 6697 ASSERT(descriptors->IsSortedNoDuplicates()); | 6637 ASSERT(descriptors->IsSortedNoDuplicates()); |
| 6698 | 6638 |
| 6699 Map* result; | 6639 Map* result; |
| 6700 MaybeObject* maybe_result = CopyDropDescriptors(); | 6640 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 6701 if (!maybe_result->To(&result)) return maybe_result; | 6641 if (!maybe_result->To(&result)) return maybe_result; |
| 6702 | 6642 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6901 | 6841 |
| 6902 // We replace the key if it is already present. | 6842 // We replace the key if it is already present. |
| 6903 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 6843 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
| 6904 if (index != DescriptorArray::kNotFound) { | 6844 if (index != DescriptorArray::kNotFound) { |
| 6905 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); | 6845 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); |
| 6906 } | 6846 } |
| 6907 return CopyAddDescriptor(descriptor, flag); | 6847 return CopyAddDescriptor(descriptor, flag); |
| 6908 } | 6848 } |
| 6909 | 6849 |
| 6910 | 6850 |
| 6851 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( |
| 6852 Handle<DescriptorArray> desc, |
| 6853 int enumeration_index, |
| 6854 PropertyAttributes attributes) { |
| 6855 CALL_HEAP_FUNCTION(desc->GetIsolate(), |
| 6856 desc->CopyUpToAddAttributes(enumeration_index, attributes), |
| 6857 DescriptorArray); |
| 6858 } |
| 6859 |
| 6860 |
| 6911 MaybeObject* DescriptorArray::CopyUpToAddAttributes( | 6861 MaybeObject* DescriptorArray::CopyUpToAddAttributes( |
| 6912 int enumeration_index, PropertyAttributes attributes) { | 6862 int enumeration_index, PropertyAttributes attributes) { |
| 6913 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | 6863 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
| 6914 | 6864 |
| 6915 int size = enumeration_index; | 6865 int size = enumeration_index; |
| 6916 | 6866 |
| 6917 DescriptorArray* descriptors; | 6867 DescriptorArray* descriptors; |
| 6918 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size); | 6868 MaybeObject* maybe_descriptors = Allocate(GetIsolate(), size); |
| 6919 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 6869 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 6920 DescriptorArray::WhitenessWitness witness(descriptors); | 6870 DescriptorArray::WhitenessWitness witness(descriptors); |
| (...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7795 DescriptorArray* src, | 7745 DescriptorArray* src, |
| 7796 int src_index, | 7746 int src_index, |
| 7797 const WhitenessWitness& witness) { | 7747 const WhitenessWitness& witness) { |
| 7798 Object* value = src->GetValue(src_index); | 7748 Object* value = src->GetValue(src_index); |
| 7799 PropertyDetails details = src->GetDetails(src_index); | 7749 PropertyDetails details = src->GetDetails(src_index); |
| 7800 Descriptor desc(src->GetKey(src_index), value, details); | 7750 Descriptor desc(src->GetKey(src_index), value, details); |
| 7801 Set(dst_index, &desc, witness); | 7751 Set(dst_index, &desc, witness); |
| 7802 } | 7752 } |
| 7803 | 7753 |
| 7804 | 7754 |
| 7755 Handle<DescriptorArray> DescriptorArray::Merge(Handle<DescriptorArray> desc, |
| 7756 int verbatim, |
| 7757 int valid, |
| 7758 int new_size, |
| 7759 int modify_index, |
| 7760 StoreMode store_mode, |
| 7761 Handle<DescriptorArray> other) { |
| 7762 CALL_HEAP_FUNCTION(desc->GetIsolate(), |
| 7763 desc->Merge(verbatim, valid, new_size, modify_index, |
| 7764 store_mode, *other), |
| 7765 DescriptorArray); |
| 7766 } |
| 7767 |
| 7768 |
| 7805 // Generalize the |other| descriptor array by merging it into the (at least | 7769 // Generalize the |other| descriptor array by merging it into the (at least |
| 7806 // partly) updated |this| descriptor array. | 7770 // partly) updated |this| descriptor array. |
| 7807 // The method merges two descriptor array in three parts. Both descriptor arrays | 7771 // The method merges two descriptor array in three parts. Both descriptor arrays |
| 7808 // are identical up to |verbatim|. They also overlap in keys up to |valid|. | 7772 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
| 7809 // Between |verbatim| and |valid|, the resulting descriptor type as well as the | 7773 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
| 7810 // representation are generalized from both |this| and |other|. Beyond |valid|, | 7774 // representation are generalized from both |this| and |other|. Beyond |valid|, |
| 7811 // the descriptors are copied verbatim from |other| up to |new_size|. | 7775 // the descriptors are copied verbatim from |other| up to |new_size|. |
| 7812 // In case of incompatible types, the type and representation of |other| is | 7776 // In case of incompatible types, the type and representation of |other| is |
| 7813 // used. | 7777 // used. |
| 7814 MaybeObject* DescriptorArray::Merge(int verbatim, | 7778 MaybeObject* DescriptorArray::Merge(int verbatim, |
| (...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9021 object->Size(); | 8985 object->Size(); |
| 9022 if ((ptr_end + AllocationMemento::kSize) <= | 8986 if ((ptr_end + AllocationMemento::kSize) <= |
| 9023 object->GetHeap()->NewSpaceTop()) { | 8987 object->GetHeap()->NewSpaceTop()) { |
| 9024 // There is room in newspace for allocation info. Do we have some? | 8988 // There is room in newspace for allocation info. Do we have some? |
| 9025 Map** possible_allocation_memento_map = | 8989 Map** possible_allocation_memento_map = |
| 9026 reinterpret_cast<Map**>(ptr_end); | 8990 reinterpret_cast<Map**>(ptr_end); |
| 9027 if (*possible_allocation_memento_map == | 8991 if (*possible_allocation_memento_map == |
| 9028 object->GetHeap()->allocation_memento_map()) { | 8992 object->GetHeap()->allocation_memento_map()) { |
| 9029 AllocationMemento* memento = AllocationMemento::cast( | 8993 AllocationMemento* memento = AllocationMemento::cast( |
| 9030 reinterpret_cast<Object*>(ptr_end + kHeapObjectTag)); | 8994 reinterpret_cast<Object*>(ptr_end + kHeapObjectTag)); |
| 9031 | 8995 return memento; |
| 9032 // TODO(mvstanton): because of chromium bug 284577, put extra care | |
| 9033 // into validating that the memento points to a valid AllocationSite. | |
| 9034 // This check is expensive so remove it asap. Also, this check | |
| 9035 // HIDES bug 284577, so it must be disabled to debug/diagnose. | |
| 9036 Object* site = memento->allocation_site(); | |
| 9037 Heap* heap = object->GetHeap(); | |
| 9038 if (heap->InOldPointerSpace(site) && | |
| 9039 site->IsHeapObject() && | |
| 9040 HeapObject::cast(site)->map() == heap->allocation_site_map()) { | |
| 9041 return memento; | |
| 9042 } | |
| 9043 } | 8996 } |
| 9044 } | 8997 } |
| 9045 } | 8998 } |
| 9046 return NULL; | 8999 return NULL; |
| 9047 } | 9000 } |
| 9048 | 9001 |
| 9049 | 9002 |
| 9050 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { | 9003 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { |
| 9051 // For array indexes mix the length into the hash as an array index could | 9004 // For array indexes mix the length into the hash as an array index could |
| 9052 // be zero. | 9005 // be zero. |
| (...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10417 cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap)); | 10370 cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap)); |
| 10418 } | 10371 } |
| 10419 } | 10372 } |
| 10420 } | 10373 } |
| 10421 } | 10374 } |
| 10422 | 10375 |
| 10423 | 10376 |
| 10424 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { | 10377 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { |
| 10425 DisallowHeapAllocation no_gc; | 10378 DisallowHeapAllocation no_gc; |
| 10426 ASSERT(kind() == FUNCTION); | 10379 ASSERT(kind() == FUNCTION); |
| 10427 for (FullCodeGenerator::BackEdgeTableIterator it(this, &no_gc); | 10380 BackEdgeTable back_edges(this, &no_gc); |
| 10428 !it.Done(); | 10381 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 10429 it.Next()) { | 10382 if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i); |
| 10430 if (it.pc_offset() == pc_offset) return it.ast_id(); | |
| 10431 } | 10383 } |
| 10432 return BailoutId::None(); | 10384 return BailoutId::None(); |
| 10433 } | 10385 } |
| 10434 | 10386 |
| 10435 | 10387 |
| 10436 bool Code::allowed_in_shared_map_code_cache() { | 10388 bool Code::allowed_in_shared_map_code_cache() { |
| 10437 return is_keyed_load_stub() || is_keyed_store_stub() || | 10389 return is_keyed_load_stub() || is_keyed_store_stub() || |
| 10438 (is_compare_ic_stub() && | 10390 (is_compare_ic_stub() && |
| 10439 ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT); | 10391 ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT); |
| 10440 } | 10392 } |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10888 } | 10840 } |
| 10889 PrintF(out, "\n"); | 10841 PrintF(out, "\n"); |
| 10890 } | 10842 } |
| 10891 PrintF(out, "\n"); | 10843 PrintF(out, "\n"); |
| 10892 } else if (kind() == FUNCTION) { | 10844 } else if (kind() == FUNCTION) { |
| 10893 unsigned offset = back_edge_table_offset(); | 10845 unsigned offset = back_edge_table_offset(); |
| 10894 // If there is no back edge table, the "table start" will be at or after | 10846 // If there is no back edge table, the "table start" will be at or after |
| 10895 // (due to alignment) the end of the instruction stream. | 10847 // (due to alignment) the end of the instruction stream. |
| 10896 if (static_cast<int>(offset) < instruction_size()) { | 10848 if (static_cast<int>(offset) < instruction_size()) { |
| 10897 DisallowHeapAllocation no_gc; | 10849 DisallowHeapAllocation no_gc; |
| 10898 FullCodeGenerator::BackEdgeTableIterator back_edges(this, &no_gc); | 10850 BackEdgeTable back_edges(this, &no_gc); |
| 10899 | 10851 |
| 10900 PrintF(out, "Back edges (size = %u)\n", back_edges.table_length()); | 10852 PrintF(out, "Back edges (size = %u)\n", back_edges.length()); |
| 10901 PrintF(out, "ast_id pc_offset loop_depth\n"); | 10853 PrintF(out, "ast_id pc_offset loop_depth\n"); |
| 10902 | 10854 |
| 10903 for ( ; !back_edges.Done(); back_edges.Next()) { | 10855 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| 10904 PrintF(out, "%6d %9u %10u\n", back_edges.ast_id().ToInt(), | 10856 PrintF(out, "%6d %9u %10u\n", back_edges.ast_id(i).ToInt(), |
| 10905 back_edges.pc_offset(), | 10857 back_edges.pc_offset(i), |
| 10906 back_edges.loop_depth()); | 10858 back_edges.loop_depth(i)); |
| 10907 } | 10859 } |
| 10908 | 10860 |
| 10909 PrintF(out, "\n"); | 10861 PrintF(out, "\n"); |
| 10910 } | 10862 } |
| 10911 #ifdef OBJECT_PRINT | 10863 #ifdef OBJECT_PRINT |
| 10912 if (!type_feedback_info()->IsUndefined()) { | 10864 if (!type_feedback_info()->IsUndefined()) { |
| 10913 TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out); | 10865 TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out); |
| 10914 PrintF(out, "\n"); | 10866 PrintF(out, "\n"); |
| 10915 } | 10867 } |
| 10916 #endif | 10868 #endif |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10967 | 10919 |
| 10968 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 10920 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 10969 Map* new_map = map(); | 10921 Map* new_map = map(); |
| 10970 if (new_elements_kind != elements_kind) { | 10922 if (new_elements_kind != elements_kind) { |
| 10971 MaybeObject* maybe = | 10923 MaybeObject* maybe = |
| 10972 GetElementsTransitionMap(GetIsolate(), new_elements_kind); | 10924 GetElementsTransitionMap(GetIsolate(), new_elements_kind); |
| 10973 if (!maybe->To(&new_map)) return maybe; | 10925 if (!maybe->To(&new_map)) return maybe; |
| 10974 } | 10926 } |
| 10975 ValidateElements(); | 10927 ValidateElements(); |
| 10976 set_map_and_elements(new_map, new_elements); | 10928 set_map_and_elements(new_map, new_elements); |
| 10929 |
| 10930 // Transition through the allocation site as well if present. |
| 10931 maybe_obj = UpdateAllocationSite(new_elements_kind); |
| 10932 if (maybe_obj->IsFailure()) return maybe_obj; |
| 10977 } else { | 10933 } else { |
| 10978 FixedArray* parameter_map = FixedArray::cast(old_elements); | 10934 FixedArray* parameter_map = FixedArray::cast(old_elements); |
| 10979 parameter_map->set(1, new_elements); | 10935 parameter_map->set(1, new_elements); |
| 10980 } | 10936 } |
| 10981 | 10937 |
| 10982 if (FLAG_trace_elements_transitions) { | 10938 if (FLAG_trace_elements_transitions) { |
| 10983 PrintElementsTransition(stdout, elements_kind, old_elements, | 10939 PrintElementsTransition(stdout, elements_kind, old_elements, |
| 10984 GetElementsKind(), new_elements); | 10940 GetElementsKind(), new_elements); |
| 10985 } | 10941 } |
| 10986 | 10942 |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11718 return GetDeclaredAccessorProperty(receiver, | 11674 return GetDeclaredAccessorProperty(receiver, |
| 11719 DeclaredAccessorInfo::cast(structure), | 11675 DeclaredAccessorInfo::cast(structure), |
| 11720 isolate); | 11676 isolate); |
| 11721 } | 11677 } |
| 11722 | 11678 |
| 11723 UNREACHABLE(); | 11679 UNREACHABLE(); |
| 11724 return NULL; | 11680 return NULL; |
| 11725 } | 11681 } |
| 11726 | 11682 |
| 11727 | 11683 |
| 11728 MaybeObject* JSObject::SetElementWithCallback(Object* structure, | 11684 Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, |
| 11729 uint32_t index, | 11685 Handle<Object> structure, |
| 11730 Object* value, | 11686 uint32_t index, |
| 11731 JSObject* holder, | 11687 Handle<Object> value, |
| 11732 StrictModeFlag strict_mode) { | 11688 Handle<JSObject> holder, |
| 11733 Isolate* isolate = GetIsolate(); | 11689 StrictModeFlag strict_mode) { |
| 11734 HandleScope scope(isolate); | 11690 Isolate* isolate = object->GetIsolate(); |
| 11735 | 11691 |
| 11736 // We should never get here to initialize a const with the hole | 11692 // We should never get here to initialize a const with the hole |
| 11737 // value since a const declaration would conflict with the setter. | 11693 // value since a const declaration would conflict with the setter. |
| 11738 ASSERT(!value->IsTheHole()); | 11694 ASSERT(!value->IsTheHole()); |
| 11739 Handle<Object> value_handle(value, isolate); | |
| 11740 | 11695 |
| 11741 // To accommodate both the old and the new api we switch on the | 11696 // To accommodate both the old and the new api we switch on the |
| 11742 // data structure used to store the callbacks. Eventually foreign | 11697 // data structure used to store the callbacks. Eventually foreign |
| 11743 // callbacks should be phased out. | 11698 // callbacks should be phased out. |
| 11744 ASSERT(!structure->IsForeign()); | 11699 ASSERT(!structure->IsForeign()); |
| 11745 | 11700 |
| 11746 if (structure->IsExecutableAccessorInfo()) { | 11701 if (structure->IsExecutableAccessorInfo()) { |
| 11747 // api style callbacks | 11702 // api style callbacks |
| 11748 Handle<JSObject> self(this); | 11703 Handle<ExecutableAccessorInfo> data = |
| 11749 Handle<JSObject> holder_handle(JSObject::cast(holder)); | 11704 Handle<ExecutableAccessorInfo>::cast(structure); |
| 11750 Handle<ExecutableAccessorInfo> data( | |
| 11751 ExecutableAccessorInfo::cast(structure)); | |
| 11752 Object* call_obj = data->setter(); | 11705 Object* call_obj = data->setter(); |
| 11753 v8::AccessorSetterCallback call_fun = | 11706 v8::AccessorSetterCallback call_fun = |
| 11754 v8::ToCData<v8::AccessorSetterCallback>(call_obj); | 11707 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 11755 if (call_fun == NULL) return value; | 11708 if (call_fun == NULL) return value; |
| 11756 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11709 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 11757 Handle<String> key(isolate->factory()->NumberToString(number)); | 11710 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 11758 LOG(isolate, ApiNamedPropertyAccess("store", *self, *key)); | 11711 LOG(isolate, ApiNamedPropertyAccess("store", *object, *key)); |
| 11759 PropertyCallbackArguments | 11712 PropertyCallbackArguments |
| 11760 args(isolate, data->data(), *self, *holder_handle); | 11713 args(isolate, data->data(), *object, *holder); |
| 11761 args.Call(call_fun, | 11714 args.Call(call_fun, |
| 11762 v8::Utils::ToLocal(key), | 11715 v8::Utils::ToLocal(key), |
| 11763 v8::Utils::ToLocal(value_handle)); | 11716 v8::Utils::ToLocal(value)); |
| 11764 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 11717 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 11765 return *value_handle; | 11718 return value; |
| 11766 } | 11719 } |
| 11767 | 11720 |
| 11768 if (structure->IsAccessorPair()) { | 11721 if (structure->IsAccessorPair()) { |
| 11769 Handle<Object> setter(AccessorPair::cast(structure)->setter(), isolate); | 11722 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
| 11770 if (setter->IsSpecFunction()) { | 11723 if (setter->IsSpecFunction()) { |
| 11771 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 11724 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 11772 return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value); | 11725 return SetPropertyWithDefinedSetter( |
| 11726 object, Handle<JSReceiver>::cast(setter), value); |
| 11773 } else { | 11727 } else { |
| 11774 if (strict_mode == kNonStrictMode) { | 11728 if (strict_mode == kNonStrictMode) { |
| 11775 return value; | 11729 return value; |
| 11776 } | 11730 } |
| 11777 Handle<Object> holder_handle(holder, isolate); | |
| 11778 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); | 11731 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); |
| 11779 Handle<Object> args[2] = { key, holder_handle }; | 11732 Handle<Object> args[2] = { key, holder }; |
| 11780 return isolate->Throw( | 11733 Handle<Object> error = isolate->factory()->NewTypeError( |
| 11781 *isolate->factory()->NewTypeError("no_setter_in_callback", | 11734 "no_setter_in_callback", HandleVector(args, 2)); |
| 11782 HandleVector(args, 2))); | 11735 isolate->Throw(*error); |
| 11736 return Handle<Object>(); |
| 11783 } | 11737 } |
| 11784 } | 11738 } |
| 11785 | 11739 |
| 11786 // TODO(dcarney): Handle correctly. | 11740 // TODO(dcarney): Handle correctly. |
| 11787 if (structure->IsDeclaredAccessorInfo()) return value; | 11741 if (structure->IsDeclaredAccessorInfo()) return value; |
| 11788 | 11742 |
| 11789 UNREACHABLE(); | 11743 UNREACHABLE(); |
| 11790 return NULL; | 11744 return Handle<Object>(); |
| 11791 } | 11745 } |
| 11792 | 11746 |
| 11793 | 11747 |
| 11794 bool JSObject::HasFastArgumentsElements() { | 11748 bool JSObject::HasFastArgumentsElements() { |
| 11795 Heap* heap = GetHeap(); | 11749 Heap* heap = GetHeap(); |
| 11796 if (!elements()->IsFixedArray()) return false; | 11750 if (!elements()->IsFixedArray()) return false; |
| 11797 FixedArray* elements = FixedArray::cast(this->elements()); | 11751 FixedArray* elements = FixedArray::cast(this->elements()); |
| 11798 if (elements->map() != heap->non_strict_arguments_elements_map()) { | 11752 if (elements->map() != heap->non_strict_arguments_elements_map()) { |
| 11799 return false; | 11753 return false; |
| 11800 } | 11754 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11977 // Insert element in the dictionary. | 11931 // Insert element in the dictionary. |
| 11978 Handle<FixedArray> elements(FixedArray::cast(this->elements())); | 11932 Handle<FixedArray> elements(FixedArray::cast(this->elements())); |
| 11979 bool is_arguments = | 11933 bool is_arguments = |
| 11980 (elements->map() == heap->non_strict_arguments_elements_map()); | 11934 (elements->map() == heap->non_strict_arguments_elements_map()); |
| 11981 Handle<SeededNumberDictionary> dictionary(is_arguments | 11935 Handle<SeededNumberDictionary> dictionary(is_arguments |
| 11982 ? SeededNumberDictionary::cast(elements->get(1)) | 11936 ? SeededNumberDictionary::cast(elements->get(1)) |
| 11983 : SeededNumberDictionary::cast(*elements)); | 11937 : SeededNumberDictionary::cast(*elements)); |
| 11984 | 11938 |
| 11985 int entry = dictionary->FindEntry(index); | 11939 int entry = dictionary->FindEntry(index); |
| 11986 if (entry != SeededNumberDictionary::kNotFound) { | 11940 if (entry != SeededNumberDictionary::kNotFound) { |
| 11987 Object* element = dictionary->ValueAt(entry); | 11941 Handle<Object> element(dictionary->ValueAt(entry), isolate); |
| 11988 PropertyDetails details = dictionary->DetailsAt(entry); | 11942 PropertyDetails details = dictionary->DetailsAt(entry); |
| 11989 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { | 11943 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { |
| 11990 return SetElementWithCallback(element, index, *value, this, strict_mode); | 11944 Handle<Object> result = SetElementWithCallback(self, element, index, |
| 11945 value, self, strict_mode); |
| 11946 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 11947 return *result; |
| 11991 } else { | 11948 } else { |
| 11992 dictionary->UpdateMaxNumberKey(index); | 11949 dictionary->UpdateMaxNumberKey(index); |
| 11993 // If a value has not been initialized we allow writing to it even if it | 11950 // If a value has not been initialized we allow writing to it even if it |
| 11994 // is read-only (a declared const that has not been initialized). If a | 11951 // is read-only (a declared const that has not been initialized). If a |
| 11995 // value is being defined we skip attribute checks completely. | 11952 // value is being defined we skip attribute checks completely. |
| 11996 if (set_mode == DEFINE_PROPERTY) { | 11953 if (set_mode == DEFINE_PROPERTY) { |
| 11997 details = PropertyDetails( | 11954 details = PropertyDetails( |
| 11998 attributes, NORMAL, details.dictionary_index()); | 11955 attributes, NORMAL, details.dictionary_index()); |
| 11999 dictionary->DetailsAtPut(entry, details); | 11956 dictionary->DetailsAtPut(entry, details); |
| 12000 } else if (details.IsReadOnly() && !element->IsTheHole()) { | 11957 } else if (details.IsReadOnly() && !element->IsTheHole()) { |
| 12001 if (strict_mode == kNonStrictMode) { | 11958 if (strict_mode == kNonStrictMode) { |
| 12002 return isolate->heap()->undefined_value(); | 11959 return isolate->heap()->undefined_value(); |
| 12003 } else { | 11960 } else { |
| 12004 Handle<Object> holder(this, isolate); | 11961 Handle<Object> holder(this, isolate); |
| 12005 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11962 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12006 Handle<Object> args[2] = { number, holder }; | 11963 Handle<Object> args[2] = { number, holder }; |
| 12007 Handle<Object> error = | 11964 Handle<Object> error = |
| 12008 isolate->factory()->NewTypeError("strict_read_only_property", | 11965 isolate->factory()->NewTypeError("strict_read_only_property", |
| 12009 HandleVector(args, 2)); | 11966 HandleVector(args, 2)); |
| 12010 return isolate->Throw(*error); | 11967 return isolate->Throw(*error); |
| 12011 } | 11968 } |
| 12012 } | 11969 } |
| 12013 // Elements of the arguments object in slow mode might be slow aliases. | 11970 // Elements of the arguments object in slow mode might be slow aliases. |
| 12014 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 11971 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
| 12015 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element); | 11972 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*element); |
| 12016 Context* context = Context::cast(elements->get(0)); | 11973 Context* context = Context::cast(elements->get(0)); |
| 12017 int context_index = entry->aliased_context_slot(); | 11974 int context_index = entry->aliased_context_slot(); |
| 12018 ASSERT(!context->get(context_index)->IsTheHole()); | 11975 ASSERT(!context->get(context_index)->IsTheHole()); |
| 12019 context->set(context_index, *value); | 11976 context->set(context_index, *value); |
| 12020 // For elements that are still writable we keep slow aliasing. | 11977 // For elements that are still writable we keep slow aliasing. |
| 12021 if (!details.IsReadOnly()) value = handle(element, isolate); | 11978 if (!details.IsReadOnly()) value = element; |
| 12022 } | 11979 } |
| 12023 dictionary->ValueAtPut(entry, *value); | 11980 dictionary->ValueAtPut(entry, *value); |
| 12024 } | 11981 } |
| 12025 } else { | 11982 } else { |
| 12026 // Index not already used. Look for an accessor in the prototype chain. | 11983 // Index not already used. Look for an accessor in the prototype chain. |
| 12027 // Can cause GC! | 11984 // Can cause GC! |
| 12028 if (check_prototype) { | 11985 if (check_prototype) { |
| 12029 bool found; | 11986 bool found; |
| 12030 MaybeObject* result = SetElementWithCallbackSetterInPrototypes( | 11987 MaybeObject* result = SetElementWithCallbackSetterInPrototypes( |
| 12031 index, *value, &found, strict_mode); | 11988 index, *value, &found, strict_mode); |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12501 | 12458 |
| 12502 // Walk through to the Allocation Site | 12459 // Walk through to the Allocation Site |
| 12503 AllocationSite* site = memento->GetAllocationSite(); | 12460 AllocationSite* site = memento->GetAllocationSite(); |
| 12504 if (site->IsLiteralSite()) { | 12461 if (site->IsLiteralSite()) { |
| 12505 JSArray* transition_info = JSArray::cast(site->transition_info()); | 12462 JSArray* transition_info = JSArray::cast(site->transition_info()); |
| 12506 ElementsKind kind = transition_info->GetElementsKind(); | 12463 ElementsKind kind = transition_info->GetElementsKind(); |
| 12507 // if kind is holey ensure that to_kind is as well. | 12464 // if kind is holey ensure that to_kind is as well. |
| 12508 if (IsHoleyElementsKind(kind)) { | 12465 if (IsHoleyElementsKind(kind)) { |
| 12509 to_kind = GetHoleyElementsKind(to_kind); | 12466 to_kind = GetHoleyElementsKind(to_kind); |
| 12510 } | 12467 } |
| 12511 if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { | 12468 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
| 12512 // If the array is huge, it's not likely to be defined in a local | 12469 // If the array is huge, it's not likely to be defined in a local |
| 12513 // function, so we shouldn't make new instances of it very often. | 12470 // function, so we shouldn't make new instances of it very often. |
| 12514 uint32_t length = 0; | 12471 uint32_t length = 0; |
| 12515 CHECK(transition_info->length()->ToArrayIndex(&length)); | 12472 CHECK(transition_info->length()->ToArrayIndex(&length)); |
| 12516 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { | 12473 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { |
| 12517 if (FLAG_trace_track_allocation_sites) { | 12474 if (FLAG_trace_track_allocation_sites) { |
| 12518 PrintF( | 12475 PrintF( |
| 12519 "AllocationSite: JSArray %p boilerplate updated %s->%s\n", | 12476 "AllocationSite: JSArray %p boilerplate updated %s->%s\n", |
| 12520 reinterpret_cast<void*>(this), | 12477 reinterpret_cast<void*>(this), |
| 12521 ElementsKindToString(kind), | 12478 ElementsKindToString(kind), |
| 12522 ElementsKindToString(to_kind)); | 12479 ElementsKindToString(to_kind)); |
| 12523 } | 12480 } |
| 12524 return transition_info->TransitionElementsKind(to_kind); | 12481 return transition_info->TransitionElementsKind(to_kind); |
| 12525 } | 12482 } |
| 12526 } | 12483 } |
| 12527 } else { | 12484 } else { |
| 12528 ElementsKind kind = site->GetElementsKind(); | 12485 ElementsKind kind = site->GetElementsKind(); |
| 12529 // if kind is holey ensure that to_kind is as well. | 12486 // if kind is holey ensure that to_kind is as well. |
| 12530 if (IsHoleyElementsKind(kind)) { | 12487 if (IsHoleyElementsKind(kind)) { |
| 12531 to_kind = GetHoleyElementsKind(to_kind); | 12488 to_kind = GetHoleyElementsKind(to_kind); |
| 12532 } | 12489 } |
| 12533 if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { | 12490 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
| 12534 if (FLAG_trace_track_allocation_sites) { | 12491 if (FLAG_trace_track_allocation_sites) { |
| 12535 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", | 12492 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", |
| 12536 reinterpret_cast<void*>(this), | 12493 reinterpret_cast<void*>(this), |
| 12537 ElementsKindToString(kind), | 12494 ElementsKindToString(kind), |
| 12538 ElementsKindToString(to_kind)); | 12495 ElementsKindToString(to_kind)); |
| 12539 } | 12496 } |
| 12540 site->set_transition_info(Smi::FromInt(to_kind)); | 12497 site->set_transition_info(Smi::FromInt(to_kind)); |
| 12541 } | 12498 } |
| 12542 } | 12499 } |
| 12543 return this; | 12500 return this; |
| (...skipping 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14517 } | 14474 } |
| 14518 | 14475 |
| 14519 | 14476 |
| 14520 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 14477 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 14521 ASSERT(!HasFastProperties()); | 14478 ASSERT(!HasFastProperties()); |
| 14522 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 14479 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 14523 return PropertyCell::cast(value); | 14480 return PropertyCell::cast(value); |
| 14524 } | 14481 } |
| 14525 | 14482 |
| 14526 | 14483 |
| 14527 // TODO(mstarzinger): Temporary wrapper until handlified. | |
| 14528 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, | |
| 14529 Handle<Name> name, | |
| 14530 Handle<Object> value, | |
| 14531 PropertyDetails details) { | |
| 14532 CALL_HEAP_FUNCTION(dict->GetIsolate(), | |
| 14533 dict->Add(*name, *value, details), | |
| 14534 NameDictionary); | |
| 14535 } | |
| 14536 | |
| 14537 | |
| 14538 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 14484 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( |
| 14539 Handle<GlobalObject> global, | 14485 Handle<GlobalObject> global, |
| 14540 Handle<Name> name) { | 14486 Handle<Name> name) { |
| 14541 ASSERT(!global->HasFastProperties()); | 14487 ASSERT(!global->HasFastProperties()); |
| 14542 int entry = global->property_dictionary()->FindEntry(*name); | 14488 int entry = global->property_dictionary()->FindEntry(*name); |
| 14543 if (entry == NameDictionary::kNotFound) { | 14489 if (entry == NameDictionary::kNotFound) { |
| 14544 Isolate* isolate = global->GetIsolate(); | 14490 Isolate* isolate = global->GetIsolate(); |
| 14545 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( | 14491 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( |
| 14546 isolate->factory()->the_hole_value()); | 14492 isolate->factory()->the_hole_value()); |
| 14547 PropertyDetails details(NONE, NORMAL, 0); | 14493 PropertyDetails details(NONE, NORMAL, 0); |
| (...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16106 isolate, DependentCode::kPropertyCellChangedGroup); | 16052 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16107 | 16053 |
| 16108 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { | 16054 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
| 16109 return *new_type; | 16055 return *new_type; |
| 16110 } | 16056 } |
| 16111 | 16057 |
| 16112 return Type::Any(); | 16058 return Type::Any(); |
| 16113 } | 16059 } |
| 16114 | 16060 |
| 16115 | 16061 |
| 16062 void PropertyCell::SetValueInferType(Handle<PropertyCell> cell, |
| 16063 Handle<Object> value, |
| 16064 WriteBarrierMode mode) { |
| 16065 CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), |
| 16066 cell->SetValueInferType(*value, mode)); |
| 16067 } |
| 16068 |
| 16069 |
| 16116 MaybeObject* PropertyCell::SetValueInferType(Object* value, | 16070 MaybeObject* PropertyCell::SetValueInferType(Object* value, |
| 16117 WriteBarrierMode ignored) { | 16071 WriteBarrierMode ignored) { |
| 16118 set_value(value, ignored); | 16072 set_value(value, ignored); |
| 16119 if (!Type::Any()->Is(type())) { | 16073 if (!Type::Any()->Is(type())) { |
| 16120 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); | 16074 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); |
| 16121 MaybeObject* maybe_type = trampoline.CallWithReturnValue( | 16075 MaybeObject* maybe_type = trampoline.CallWithReturnValue( |
| 16122 &PropertyCell::UpdateType, | 16076 &PropertyCell::UpdateType, |
| 16123 Handle<PropertyCell>(this), | 16077 Handle<PropertyCell>(this), |
| 16124 Handle<Object>(value, GetIsolate())); | 16078 Handle<Object>(value, GetIsolate())); |
| 16125 Type* new_type = NULL; | 16079 Type* new_type = NULL; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 16154 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16108 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16155 static const char* error_messages_[] = { | 16109 static const char* error_messages_[] = { |
| 16156 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16110 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16157 }; | 16111 }; |
| 16158 #undef ERROR_MESSAGES_TEXTS | 16112 #undef ERROR_MESSAGES_TEXTS |
| 16159 return error_messages_[reason]; | 16113 return error_messages_[reason]; |
| 16160 } | 16114 } |
| 16161 | 16115 |
| 16162 | 16116 |
| 16163 } } // namespace v8::internal | 16117 } } // namespace v8::internal |
| OLD | NEW |