| 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 21 matching lines...) Expand all Loading... |
| 32 #include "arguments.h" | 32 #include "arguments.h" |
| 33 #include "bootstrapper.h" | 33 #include "bootstrapper.h" |
| 34 #include "codegen.h" | 34 #include "codegen.h" |
| 35 #include "debug.h" | 35 #include "debug.h" |
| 36 #include "deoptimizer.h" | 36 #include "deoptimizer.h" |
| 37 #include "date.h" | 37 #include "date.h" |
| 38 #include "elements.h" | 38 #include "elements.h" |
| 39 #include "execution.h" | 39 #include "execution.h" |
| 40 #include "full-codegen.h" | 40 #include "full-codegen.h" |
| 41 #include "hydrogen.h" | 41 #include "hydrogen.h" |
| 42 #include "isolate-inl.h" |
| 42 #include "objects-inl.h" | 43 #include "objects-inl.h" |
| 43 #include "objects-visiting.h" | 44 #include "objects-visiting.h" |
| 44 #include "objects-visiting-inl.h" | 45 #include "objects-visiting-inl.h" |
| 45 #include "macro-assembler.h" | 46 #include "macro-assembler.h" |
| 46 #include "mark-compact.h" | 47 #include "mark-compact.h" |
| 47 #include "safepoint-table.h" | 48 #include "safepoint-table.h" |
| 48 #include "string-stream.h" | 49 #include "string-stream.h" |
| 49 #include "utils.h" | 50 #include "utils.h" |
| 50 | 51 |
| 51 #ifdef ENABLE_DISASSEMBLER | 52 #ifdef ENABLE_DISASSEMBLER |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 ASSERT(!HasFastProperties()); | 623 ASSERT(!HasFastProperties()); |
| 623 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 624 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 624 if (IsGlobalObject()) { | 625 if (IsGlobalObject()) { |
| 625 value = PropertyCell::cast(value)->value(); | 626 value = PropertyCell::cast(value)->value(); |
| 626 } | 627 } |
| 627 ASSERT(!value->IsPropertyCell() && !value->IsCell()); | 628 ASSERT(!value->IsPropertyCell() && !value->IsCell()); |
| 628 return value; | 629 return value; |
| 629 } | 630 } |
| 630 | 631 |
| 631 | 632 |
| 632 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) { | 633 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 634 LookupResult* result, |
| 635 Handle<Object> value) { |
| 636 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 637 object->SetNormalizedProperty(result, *value), |
| 638 Object); |
| 639 } |
| 640 |
| 641 |
| 642 MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result, |
| 643 Object* value) { |
| 633 ASSERT(!HasFastProperties()); | 644 ASSERT(!HasFastProperties()); |
| 634 if (IsGlobalObject()) { | 645 if (IsGlobalObject()) { |
| 635 PropertyCell* cell = PropertyCell::cast( | 646 PropertyCell* cell = PropertyCell::cast( |
| 636 property_dictionary()->ValueAt(result->GetDictionaryEntry())); | 647 property_dictionary()->ValueAt(result->GetDictionaryEntry())); |
| 637 cell->set_value(value); | 648 MaybeObject* maybe_type = cell->SetValueInferType(value); |
| 649 if (maybe_type->IsFailure()) return maybe_type; |
| 638 } else { | 650 } else { |
| 639 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | 651 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
| 640 } | 652 } |
| 641 return value; | 653 return value; |
| 642 } | 654 } |
| 643 | 655 |
| 644 | 656 |
| 645 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, | 657 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, |
| 646 Handle<Name> key, | 658 Handle<Name> key, |
| 647 Handle<Object> value, | 659 Handle<Object> value, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 enumeration_index = original_details.dictionary_index(); | 695 enumeration_index = original_details.dictionary_index(); |
| 684 ASSERT(enumeration_index > 0); | 696 ASSERT(enumeration_index > 0); |
| 685 } | 697 } |
| 686 | 698 |
| 687 details = PropertyDetails( | 699 details = PropertyDetails( |
| 688 details.attributes(), details.type(), enumeration_index); | 700 details.attributes(), details.type(), enumeration_index); |
| 689 | 701 |
| 690 if (IsGlobalObject()) { | 702 if (IsGlobalObject()) { |
| 691 PropertyCell* cell = | 703 PropertyCell* cell = |
| 692 PropertyCell::cast(property_dictionary()->ValueAt(entry)); | 704 PropertyCell::cast(property_dictionary()->ValueAt(entry)); |
| 693 cell->set_value(value); | 705 MaybeObject* maybe_type = cell->SetValueInferType(value); |
| 706 if (maybe_type->IsFailure()) return maybe_type; |
| 694 // Please note we have to update the property details. | 707 // Please note we have to update the property details. |
| 695 property_dictionary()->DetailsAtPut(entry, details); | 708 property_dictionary()->DetailsAtPut(entry, details); |
| 696 } else { | 709 } else { |
| 697 property_dictionary()->SetEntry(entry, name, value, details); | 710 property_dictionary()->SetEntry(entry, name, value, details); |
| 698 } | 711 } |
| 699 return value; | 712 return value; |
| 700 } | 713 } |
| 701 | 714 |
| 702 | 715 |
| 703 MaybeObject* JSObject::DeleteNormalizedProperty(Name* name, DeleteMode mode) { | 716 MaybeObject* JSObject::DeleteNormalizedProperty(Name* name, DeleteMode mode) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 715 // from the DontDelete cell without checking if it contains | 728 // from the DontDelete cell without checking if it contains |
| 716 // the hole value. | 729 // the hole value. |
| 717 Map* new_map; | 730 Map* new_map; |
| 718 MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 731 MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 719 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 732 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 720 | 733 |
| 721 ASSERT(new_map->is_dictionary_map()); | 734 ASSERT(new_map->is_dictionary_map()); |
| 722 set_map(new_map); | 735 set_map(new_map); |
| 723 } | 736 } |
| 724 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); | 737 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); |
| 725 cell->set_value(cell->GetHeap()->the_hole_value()); | 738 MaybeObject* maybe_type = |
| 739 cell->SetValueInferType(cell->GetHeap()->the_hole_value()); |
| 740 if (maybe_type->IsFailure()) return maybe_type; |
| 726 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 741 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 727 } else { | 742 } else { |
| 728 Object* deleted = dictionary->DeleteProperty(entry, mode); | 743 Object* deleted = dictionary->DeleteProperty(entry, mode); |
| 729 if (deleted == GetHeap()->true_value()) { | 744 if (deleted == GetHeap()->true_value()) { |
| 730 FixedArray* new_properties = NULL; | 745 FixedArray* new_properties = NULL; |
| 731 MaybeObject* maybe_properties = dictionary->Shrink(name); | 746 MaybeObject* maybe_properties = dictionary->Shrink(name); |
| 732 if (!maybe_properties->To(&new_properties)) { | 747 if (!maybe_properties->To(&new_properties)) { |
| 733 return maybe_properties; | 748 return maybe_properties; |
| 734 } | 749 } |
| 735 set_properties(new_properties); | 750 set_properties(new_properties); |
| (...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 Object* value, | 1937 Object* value, |
| 1923 PropertyAttributes attributes) { | 1938 PropertyAttributes attributes) { |
| 1924 ASSERT(!HasFastProperties()); | 1939 ASSERT(!HasFastProperties()); |
| 1925 NameDictionary* dict = property_dictionary(); | 1940 NameDictionary* dict = property_dictionary(); |
| 1926 Object* store_value = value; | 1941 Object* store_value = value; |
| 1927 if (IsGlobalObject()) { | 1942 if (IsGlobalObject()) { |
| 1928 // In case name is an orphaned property reuse the cell. | 1943 // In case name is an orphaned property reuse the cell. |
| 1929 int entry = dict->FindEntry(name); | 1944 int entry = dict->FindEntry(name); |
| 1930 if (entry != NameDictionary::kNotFound) { | 1945 if (entry != NameDictionary::kNotFound) { |
| 1931 store_value = dict->ValueAt(entry); | 1946 store_value = dict->ValueAt(entry); |
| 1932 PropertyCell::cast(store_value)->set_value(value); | 1947 MaybeObject* maybe_type = |
| 1948 PropertyCell::cast(store_value)->SetValueInferType(value); |
| 1949 if (maybe_type->IsFailure()) return maybe_type; |
| 1933 // Assign an enumeration index to the property and update | 1950 // Assign an enumeration index to the property and update |
| 1934 // SetNextEnumerationIndex. | 1951 // SetNextEnumerationIndex. |
| 1935 int index = dict->NextEnumerationIndex(); | 1952 int index = dict->NextEnumerationIndex(); |
| 1936 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); | 1953 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
| 1937 dict->SetNextEnumerationIndex(index + 1); | 1954 dict->SetNextEnumerationIndex(index + 1); |
| 1938 dict->SetEntry(entry, name, store_value, details); | 1955 dict->SetEntry(entry, name, store_value, details); |
| 1939 return value; | 1956 return value; |
| 1940 } | 1957 } |
| 1941 Heap* heap = GetHeap(); | 1958 Heap* heap = GetHeap(); |
| 1942 { MaybeObject* maybe_store_value = | 1959 { MaybeObject* maybe_store_value = |
| 1943 heap->AllocatePropertyCell(value); | 1960 heap->AllocatePropertyCell(value); |
| 1944 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | 1961 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| 1945 } | 1962 } |
| 1946 PropertyCell::cast(store_value)->set_value(value); | 1963 MaybeObject* maybe_type = |
| 1964 PropertyCell::cast(store_value)->SetValueInferType(value); |
| 1965 if (maybe_type->IsFailure()) return maybe_type; |
| 1947 } | 1966 } |
| 1948 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 1967 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
| 1949 Object* result; | 1968 Object* result; |
| 1950 { MaybeObject* maybe_result = dict->Add(name, store_value, details); | 1969 { MaybeObject* maybe_result = dict->Add(name, store_value, details); |
| 1951 if (!maybe_result->ToObject(&result)) return maybe_result; | 1970 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1952 } | 1971 } |
| 1953 if (dict != result) set_properties(NameDictionary::cast(result)); | 1972 if (dict != result) set_properties(NameDictionary::cast(result)); |
| 1954 return value; | 1973 return value; |
| 1955 } | 1974 } |
| 1956 | 1975 |
| (...skipping 3874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5831 PropertyDetails(attributes, CALLBACKS, index)); | 5850 PropertyDetails(attributes, CALLBACKS, index)); |
| 5832 } | 5851 } |
| 5833 AccessorPair::cast(result)->SetComponents(getter, setter); | 5852 AccessorPair::cast(result)->SetComponents(getter, setter); |
| 5834 return true; | 5853 return true; |
| 5835 } | 5854 } |
| 5836 } | 5855 } |
| 5837 return false; | 5856 return false; |
| 5838 } | 5857 } |
| 5839 | 5858 |
| 5840 | 5859 |
| 5841 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, | 5860 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
| 5842 Object* getter, | 5861 uint32_t index, |
| 5843 Object* setter, | 5862 Handle<Object> getter, |
| 5844 PropertyAttributes attributes) { | 5863 Handle<Object> setter, |
| 5845 switch (GetElementsKind()) { | 5864 PropertyAttributes attributes) { |
| 5865 switch (object->GetElementsKind()) { |
| 5846 case FAST_SMI_ELEMENTS: | 5866 case FAST_SMI_ELEMENTS: |
| 5847 case FAST_ELEMENTS: | 5867 case FAST_ELEMENTS: |
| 5848 case FAST_DOUBLE_ELEMENTS: | 5868 case FAST_DOUBLE_ELEMENTS: |
| 5849 case FAST_HOLEY_SMI_ELEMENTS: | 5869 case FAST_HOLEY_SMI_ELEMENTS: |
| 5850 case FAST_HOLEY_ELEMENTS: | 5870 case FAST_HOLEY_ELEMENTS: |
| 5851 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5871 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 5852 break; | 5872 break; |
| 5853 case EXTERNAL_PIXEL_ELEMENTS: | 5873 case EXTERNAL_PIXEL_ELEMENTS: |
| 5854 case EXTERNAL_BYTE_ELEMENTS: | 5874 case EXTERNAL_BYTE_ELEMENTS: |
| 5855 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 5875 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 5856 case EXTERNAL_SHORT_ELEMENTS: | 5876 case EXTERNAL_SHORT_ELEMENTS: |
| 5857 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 5877 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 5858 case EXTERNAL_INT_ELEMENTS: | 5878 case EXTERNAL_INT_ELEMENTS: |
| 5859 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 5879 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 5860 case EXTERNAL_FLOAT_ELEMENTS: | 5880 case EXTERNAL_FLOAT_ELEMENTS: |
| 5861 case EXTERNAL_DOUBLE_ELEMENTS: | 5881 case EXTERNAL_DOUBLE_ELEMENTS: |
| 5862 // Ignore getters and setters on pixel and external array elements. | 5882 // Ignore getters and setters on pixel and external array elements. |
| 5863 return GetHeap()->undefined_value(); | 5883 return; |
| 5864 case DICTIONARY_ELEMENTS: | 5884 case DICTIONARY_ELEMENTS: |
| 5865 if (UpdateGetterSetterInDictionary(element_dictionary(), | 5885 if (UpdateGetterSetterInDictionary(object->element_dictionary(), |
| 5866 index, | 5886 index, |
| 5867 getter, | 5887 *getter, |
| 5868 setter, | 5888 *setter, |
| 5869 attributes)) { | 5889 attributes)) { |
| 5870 return GetHeap()->undefined_value(); | 5890 return; |
| 5871 } | 5891 } |
| 5872 break; | 5892 break; |
| 5873 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 5893 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 5874 // Ascertain whether we have read-only properties or an existing | 5894 // Ascertain whether we have read-only properties or an existing |
| 5875 // getter/setter pair in an arguments elements dictionary backing | 5895 // getter/setter pair in an arguments elements dictionary backing |
| 5876 // store. | 5896 // store. |
| 5877 FixedArray* parameter_map = FixedArray::cast(elements()); | 5897 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 5878 uint32_t length = parameter_map->length(); | 5898 uint32_t length = parameter_map->length(); |
| 5879 Object* probe = | 5899 Object* probe = |
| 5880 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | 5900 index < (length - 2) ? parameter_map->get(index + 2) : NULL; |
| 5881 if (probe == NULL || probe->IsTheHole()) { | 5901 if (probe == NULL || probe->IsTheHole()) { |
| 5882 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 5902 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 5883 if (arguments->IsDictionary()) { | 5903 if (arguments->IsDictionary()) { |
| 5884 SeededNumberDictionary* dictionary = | 5904 SeededNumberDictionary* dictionary = |
| 5885 SeededNumberDictionary::cast(arguments); | 5905 SeededNumberDictionary::cast(arguments); |
| 5886 if (UpdateGetterSetterInDictionary(dictionary, | 5906 if (UpdateGetterSetterInDictionary(dictionary, |
| 5887 index, | 5907 index, |
| 5888 getter, | 5908 *getter, |
| 5889 setter, | 5909 *setter, |
| 5890 attributes)) { | 5910 attributes)) { |
| 5891 return GetHeap()->undefined_value(); | 5911 return; |
| 5892 } | 5912 } |
| 5893 } | 5913 } |
| 5894 } | 5914 } |
| 5895 break; | 5915 break; |
| 5896 } | 5916 } |
| 5897 } | 5917 } |
| 5898 | 5918 |
| 5899 AccessorPair* accessors; | 5919 Isolate* isolate = object->GetIsolate(); |
| 5900 { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair(); | 5920 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); |
| 5901 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | 5921 accessors->SetComponents(*getter, *setter); |
| 5902 } | |
| 5903 accessors->SetComponents(getter, setter); | |
| 5904 | 5922 |
| 5905 return SetElementCallback(index, accessors, attributes); | 5923 CALL_HEAP_FUNCTION_VOID( |
| 5924 isolate, object->SetElementCallback(index, *accessors, attributes)); |
| 5906 } | 5925 } |
| 5907 | 5926 |
| 5908 | 5927 |
| 5909 MaybeObject* JSObject::CreateAccessorPairFor(Name* name) { | 5928 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object, |
| 5910 LookupResult result(GetHeap()->isolate()); | 5929 Handle<Name> name) { |
| 5911 LocalLookupRealNamedProperty(name, &result); | 5930 Isolate* isolate = object->GetIsolate(); |
| 5931 LookupResult result(isolate); |
| 5932 object->LocalLookupRealNamedProperty(*name, &result); |
| 5912 if (result.IsPropertyCallbacks()) { | 5933 if (result.IsPropertyCallbacks()) { |
| 5913 // Note that the result can actually have IsDontDelete() == true when we | 5934 // Note that the result can actually have IsDontDelete() == true when we |
| 5914 // e.g. have to fall back to the slow case while adding a setter after | 5935 // e.g. have to fall back to the slow case while adding a setter after |
| 5915 // successfully reusing a map transition for a getter. Nevertheless, this is | 5936 // successfully reusing a map transition for a getter. Nevertheless, this is |
| 5916 // OK, because the assertion only holds for the whole addition of both | 5937 // OK, because the assertion only holds for the whole addition of both |
| 5917 // accessors, not for the addition of each part. See first comment in | 5938 // accessors, not for the addition of each part. See first comment in |
| 5918 // DefinePropertyAccessor below. | 5939 // DefinePropertyAccessor below. |
| 5919 Object* obj = result.GetCallbackObject(); | 5940 Object* obj = result.GetCallbackObject(); |
| 5920 if (obj->IsAccessorPair()) { | 5941 if (obj->IsAccessorPair()) { |
| 5921 return AccessorPair::cast(obj)->Copy(); | 5942 return AccessorPair::Copy(handle(AccessorPair::cast(obj), isolate)); |
| 5922 } | 5943 } |
| 5923 } | 5944 } |
| 5924 return GetHeap()->AllocateAccessorPair(); | 5945 return isolate->factory()->NewAccessorPair(); |
| 5925 } | 5946 } |
| 5926 | 5947 |
| 5927 | 5948 |
| 5928 MaybeObject* JSObject::DefinePropertyAccessor(Name* name, | 5949 void JSObject::DefinePropertyAccessor(Handle<JSObject> object, |
| 5929 Object* getter, | 5950 Handle<Name> name, |
| 5930 Object* setter, | 5951 Handle<Object> getter, |
| 5931 PropertyAttributes attributes) { | 5952 Handle<Object> setter, |
| 5953 PropertyAttributes attributes) { |
| 5932 // We could assert that the property is configurable here, but we would need | 5954 // We could assert that the property is configurable here, but we would need |
| 5933 // to do a lookup, which seems to be a bit of overkill. | 5955 // to do a lookup, which seems to be a bit of overkill. |
| 5934 Heap* heap = GetHeap(); | |
| 5935 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); | 5956 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); |
| 5936 if (HasFastProperties() && !only_attribute_changes && | 5957 if (object->HasFastProperties() && !only_attribute_changes && |
| 5937 (map()->NumberOfOwnDescriptors() < | 5958 (object->map()->NumberOfOwnDescriptors() < |
| 5938 DescriptorArray::kMaxNumberOfDescriptors)) { | 5959 DescriptorArray::kMaxNumberOfDescriptors)) { |
| 5939 MaybeObject* getterOk = heap->undefined_value(); | 5960 bool getterOk = getter->IsNull() || |
| 5940 if (!getter->IsNull()) { | 5961 DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes); |
| 5941 getterOk = DefineFastAccessor(name, ACCESSOR_GETTER, getter, attributes); | 5962 bool setterOk = !getterOk || setter->IsNull() || |
| 5942 if (getterOk->IsFailure()) return getterOk; | 5963 DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes); |
| 5943 } | 5964 if (getterOk && setterOk) return; |
| 5944 | |
| 5945 MaybeObject* setterOk = heap->undefined_value(); | |
| 5946 if (getterOk != heap->null_value() && !setter->IsNull()) { | |
| 5947 setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes); | |
| 5948 if (setterOk->IsFailure()) return setterOk; | |
| 5949 } | |
| 5950 | |
| 5951 if (getterOk != heap->null_value() && setterOk != heap->null_value()) { | |
| 5952 return heap->undefined_value(); | |
| 5953 } | |
| 5954 } | 5965 } |
| 5955 | 5966 |
| 5956 AccessorPair* accessors; | 5967 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); |
| 5957 MaybeObject* maybe_accessors = CreateAccessorPairFor(name); | 5968 accessors->SetComponents(*getter, *setter); |
| 5958 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | |
| 5959 | 5969 |
| 5960 accessors->SetComponents(getter, setter); | 5970 CALL_HEAP_FUNCTION_VOID( |
| 5961 return SetPropertyCallback(name, accessors, attributes); | 5971 object->GetIsolate(), |
| 5972 object->SetPropertyCallback(*name, *accessors, attributes)); |
| 5962 } | 5973 } |
| 5963 | 5974 |
| 5964 | 5975 |
| 5965 bool JSObject::CanSetCallback(Name* name) { | 5976 bool JSObject::CanSetCallback(Name* name) { |
| 5966 ASSERT(!IsAccessCheckNeeded() || | 5977 ASSERT(!IsAccessCheckNeeded() || |
| 5967 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 5978 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 5968 | 5979 |
| 5969 // Check if there is an API defined callback object which prohibits | 5980 // Check if there is an API defined callback object which prohibits |
| 5970 // callback overwriting in this object or its prototype chain. | 5981 // callback overwriting in this object or its prototype chain. |
| 5971 // This mechanism is needed for instance in a browser setting, where | 5982 // This mechanism is needed for instance in a browser setting, where |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6053 | 6064 |
| 6054 return GetHeap()->undefined_value(); | 6065 return GetHeap()->undefined_value(); |
| 6055 } | 6066 } |
| 6056 | 6067 |
| 6057 | 6068 |
| 6058 void JSObject::DefineAccessor(Handle<JSObject> object, | 6069 void JSObject::DefineAccessor(Handle<JSObject> object, |
| 6059 Handle<Name> name, | 6070 Handle<Name> name, |
| 6060 Handle<Object> getter, | 6071 Handle<Object> getter, |
| 6061 Handle<Object> setter, | 6072 Handle<Object> setter, |
| 6062 PropertyAttributes attributes) { | 6073 PropertyAttributes attributes) { |
| 6063 CALL_HEAP_FUNCTION_VOID( | 6074 Isolate* isolate = object->GetIsolate(); |
| 6064 object->GetIsolate(), | |
| 6065 object->DefineAccessor(*name, *getter, *setter, attributes)); | |
| 6066 } | |
| 6067 | |
| 6068 MaybeObject* JSObject::DefineAccessor(Name* name_raw, | |
| 6069 Object* getter_raw, | |
| 6070 Object* setter_raw, | |
| 6071 PropertyAttributes attributes) { | |
| 6072 Isolate* isolate = GetIsolate(); | |
| 6073 // Check access rights if needed. | 6075 // Check access rights if needed. |
| 6074 if (IsAccessCheckNeeded() && | 6076 if (object->IsAccessCheckNeeded() && |
| 6075 !isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 6077 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 6076 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 6078 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
| 6077 return isolate->heap()->undefined_value(); | 6079 return; |
| 6078 } | 6080 } |
| 6079 | 6081 |
| 6080 if (IsJSGlobalProxy()) { | 6082 if (object->IsJSGlobalProxy()) { |
| 6081 Object* proto = GetPrototype(); | 6083 Handle<Object> proto(object->GetPrototype(), isolate); |
| 6082 if (proto->IsNull()) return this; | 6084 if (proto->IsNull()) return; |
| 6083 ASSERT(proto->IsJSGlobalObject()); | 6085 ASSERT(proto->IsJSGlobalObject()); |
| 6084 return JSObject::cast(proto)->DefineAccessor( | 6086 DefineAccessor( |
| 6085 name_raw, getter_raw, setter_raw, attributes); | 6087 Handle<JSObject>::cast(proto), name, getter, setter, attributes); |
| 6088 return; |
| 6086 } | 6089 } |
| 6087 | 6090 |
| 6088 // Make sure that the top context does not change when doing callbacks or | 6091 // Make sure that the top context does not change when doing callbacks or |
| 6089 // interceptor calls. | 6092 // interceptor calls. |
| 6090 AssertNoContextChange ncc; | 6093 AssertNoContextChange ncc; |
| 6091 | 6094 |
| 6092 // Try to flatten before operating on the string. | 6095 // Try to flatten before operating on the string. |
| 6093 if (name_raw->IsString()) String::cast(name_raw)->TryFlatten(); | 6096 if (name->IsString()) String::cast(*name)->TryFlatten(); |
| 6094 | 6097 |
| 6095 if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value(); | 6098 if (!object->CanSetCallback(*name)) return; |
| 6096 | |
| 6097 // From this point on everything needs to be handlified. | |
| 6098 HandleScope scope(isolate); | |
| 6099 Handle<JSObject> self(this); | |
| 6100 Handle<Name> name(name_raw); | |
| 6101 Handle<Object> getter(getter_raw, isolate); | |
| 6102 Handle<Object> setter(setter_raw, isolate); | |
| 6103 | 6099 |
| 6104 uint32_t index = 0; | 6100 uint32_t index = 0; |
| 6105 bool is_element = name->AsArrayIndex(&index); | 6101 bool is_element = name->AsArrayIndex(&index); |
| 6106 | 6102 |
| 6107 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6103 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6108 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 6104 bool is_observed = FLAG_harmony_observation && object->map()->is_observed(); |
| 6109 bool preexists = false; | 6105 bool preexists = false; |
| 6110 if (is_observed) { | 6106 if (is_observed) { |
| 6111 if (is_element) { | 6107 if (is_element) { |
| 6112 preexists = HasLocalElement(index); | 6108 preexists = object->HasLocalElement(index); |
| 6113 if (preexists && self->GetLocalElementAccessorPair(index) == NULL) { | 6109 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
| 6114 old_value = Object::GetElement(self, index); | 6110 old_value = Object::GetElement(object, index); |
| 6115 } | 6111 } |
| 6116 } else { | 6112 } else { |
| 6117 LookupResult lookup(isolate); | 6113 LookupResult lookup(isolate); |
| 6118 LocalLookup(*name, &lookup, true); | 6114 object->LocalLookup(*name, &lookup, true); |
| 6119 preexists = lookup.IsProperty(); | 6115 preexists = lookup.IsProperty(); |
| 6120 if (preexists && lookup.IsDataProperty()) { | 6116 if (preexists && lookup.IsDataProperty()) { |
| 6121 old_value = Object::GetProperty(self, name); | 6117 old_value = Object::GetProperty(object, name); |
| 6122 } | 6118 } |
| 6123 } | 6119 } |
| 6124 } | 6120 } |
| 6125 | 6121 |
| 6126 MaybeObject* result = is_element ? | 6122 if (is_element) { |
| 6127 self->DefineElementAccessor(index, *getter, *setter, attributes) : | 6123 DefineElementAccessor(object, index, getter, setter, attributes); |
| 6128 self->DefinePropertyAccessor(*name, *getter, *setter, attributes); | 6124 } else { |
| 6129 | 6125 DefinePropertyAccessor(object, name, getter, setter, attributes); |
| 6130 Handle<Object> hresult; | 6126 } |
| 6131 if (!result->ToHandle(&hresult, isolate)) return result; | |
| 6132 | 6127 |
| 6133 if (is_observed) { | 6128 if (is_observed) { |
| 6134 const char* type = preexists ? "reconfigured" : "new"; | 6129 const char* type = preexists ? "reconfigured" : "new"; |
| 6135 EnqueueChangeRecord(self, type, name, old_value); | 6130 EnqueueChangeRecord(object, type, name, old_value); |
| 6136 } | 6131 } |
| 6137 | |
| 6138 return *hresult; | |
| 6139 } | 6132 } |
| 6140 | 6133 |
| 6141 | 6134 |
| 6142 static MaybeObject* TryAccessorTransition(JSObject* self, | 6135 static bool TryAccessorTransition(JSObject* self, |
| 6143 Map* transitioned_map, | 6136 Map* transitioned_map, |
| 6144 int target_descriptor, | 6137 int target_descriptor, |
| 6145 AccessorComponent component, | 6138 AccessorComponent component, |
| 6146 Object* accessor, | 6139 Object* accessor, |
| 6147 PropertyAttributes attributes) { | 6140 PropertyAttributes attributes) { |
| 6148 DescriptorArray* descs = transitioned_map->instance_descriptors(); | 6141 DescriptorArray* descs = transitioned_map->instance_descriptors(); |
| 6149 PropertyDetails details = descs->GetDetails(target_descriptor); | 6142 PropertyDetails details = descs->GetDetails(target_descriptor); |
| 6150 | 6143 |
| 6151 // If the transition target was not callbacks, fall back to the slow case. | 6144 // If the transition target was not callbacks, fall back to the slow case. |
| 6152 if (details.type() != CALLBACKS) return self->GetHeap()->null_value(); | 6145 if (details.type() != CALLBACKS) return false; |
| 6153 Object* descriptor = descs->GetCallbacksObject(target_descriptor); | 6146 Object* descriptor = descs->GetCallbacksObject(target_descriptor); |
| 6154 if (!descriptor->IsAccessorPair()) return self->GetHeap()->null_value(); | 6147 if (!descriptor->IsAccessorPair()) return false; |
| 6155 | 6148 |
| 6156 Object* target_accessor = AccessorPair::cast(descriptor)->get(component); | 6149 Object* target_accessor = AccessorPair::cast(descriptor)->get(component); |
| 6157 PropertyAttributes target_attributes = details.attributes(); | 6150 PropertyAttributes target_attributes = details.attributes(); |
| 6158 | 6151 |
| 6159 // Reuse transition if adding same accessor with same attributes. | 6152 // Reuse transition if adding same accessor with same attributes. |
| 6160 if (target_accessor == accessor && target_attributes == attributes) { | 6153 if (target_accessor == accessor && target_attributes == attributes) { |
| 6161 self->set_map(transitioned_map); | 6154 self->set_map(transitioned_map); |
| 6162 return self; | 6155 return true; |
| 6163 } | 6156 } |
| 6164 | 6157 |
| 6165 // If either not the same accessor, or not the same attributes, fall back to | 6158 // If either not the same accessor, or not the same attributes, fall back to |
| 6166 // the slow case. | 6159 // the slow case. |
| 6167 return self->GetHeap()->null_value(); | 6160 return false; |
| 6168 } | 6161 } |
| 6169 | 6162 |
| 6170 | 6163 |
| 6171 MaybeObject* JSObject::DefineFastAccessor(Name* name, | 6164 static MaybeObject* CopyInsertDescriptor(Map* map, |
| 6172 AccessorComponent component, | 6165 Name* name, |
| 6173 Object* accessor, | 6166 AccessorPair* accessors, |
| 6174 PropertyAttributes attributes) { | 6167 PropertyAttributes attributes) { |
| 6168 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); |
| 6169 return map->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION); |
| 6170 } |
| 6171 |
| 6172 |
| 6173 static Handle<Map> CopyInsertDescriptor(Handle<Map> map, |
| 6174 Handle<Name> name, |
| 6175 Handle<AccessorPair> accessors, |
| 6176 PropertyAttributes attributes) { |
| 6177 CALL_HEAP_FUNCTION(map->GetIsolate(), |
| 6178 CopyInsertDescriptor(*map, *name, *accessors, attributes), |
| 6179 Map); |
| 6180 } |
| 6181 |
| 6182 |
| 6183 bool JSObject::DefineFastAccessor(Handle<JSObject> object, |
| 6184 Handle<Name> name, |
| 6185 AccessorComponent component, |
| 6186 Handle<Object> accessor, |
| 6187 PropertyAttributes attributes) { |
| 6175 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); | 6188 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); |
| 6176 LookupResult result(GetIsolate()); | 6189 Isolate* isolate = object->GetIsolate(); |
| 6177 LocalLookup(name, &result); | 6190 LookupResult result(isolate); |
| 6191 object->LocalLookup(*name, &result); |
| 6178 | 6192 |
| 6179 if (result.IsFound() && !result.IsPropertyCallbacks()) { | 6193 if (result.IsFound() && !result.IsPropertyCallbacks()) { |
| 6180 return GetHeap()->null_value(); | 6194 return false; |
| 6181 } | 6195 } |
| 6182 | 6196 |
| 6183 // Return success if the same accessor with the same attributes already exist. | 6197 // Return success if the same accessor with the same attributes already exist. |
| 6184 AccessorPair* source_accessors = NULL; | 6198 AccessorPair* source_accessors = NULL; |
| 6185 if (result.IsPropertyCallbacks()) { | 6199 if (result.IsPropertyCallbacks()) { |
| 6186 Object* callback_value = result.GetCallbackObject(); | 6200 Object* callback_value = result.GetCallbackObject(); |
| 6187 if (callback_value->IsAccessorPair()) { | 6201 if (callback_value->IsAccessorPair()) { |
| 6188 source_accessors = AccessorPair::cast(callback_value); | 6202 source_accessors = AccessorPair::cast(callback_value); |
| 6189 Object* entry = source_accessors->get(component); | 6203 Object* entry = source_accessors->get(component); |
| 6190 if (entry == accessor && result.GetAttributes() == attributes) { | 6204 if (entry == *accessor && result.GetAttributes() == attributes) { |
| 6191 return this; | 6205 return true; |
| 6192 } | 6206 } |
| 6193 } else { | 6207 } else { |
| 6194 return GetHeap()->null_value(); | 6208 return false; |
| 6195 } | 6209 } |
| 6196 | 6210 |
| 6197 int descriptor_number = result.GetDescriptorIndex(); | 6211 int descriptor_number = result.GetDescriptorIndex(); |
| 6198 | 6212 |
| 6199 map()->LookupTransition(this, name, &result); | 6213 object->map()->LookupTransition(*object, *name, &result); |
| 6200 | 6214 |
| 6201 if (result.IsFound()) { | 6215 if (result.IsFound()) { |
| 6202 Map* target = result.GetTransitionTarget(); | 6216 Map* target = result.GetTransitionTarget(); |
| 6203 ASSERT(target->NumberOfOwnDescriptors() == | 6217 ASSERT(target->NumberOfOwnDescriptors() == |
| 6204 map()->NumberOfOwnDescriptors()); | 6218 object->map()->NumberOfOwnDescriptors()); |
| 6205 // This works since descriptors are sorted in order of addition. | 6219 // This works since descriptors are sorted in order of addition. |
| 6206 ASSERT(map()->instance_descriptors()->GetKey(descriptor_number) == name); | 6220 ASSERT(object->map()->instance_descriptors()-> |
| 6207 return TryAccessorTransition( | 6221 GetKey(descriptor_number) == *name); |
| 6208 this, target, descriptor_number, component, accessor, attributes); | 6222 return TryAccessorTransition(*object, target, descriptor_number, |
| 6223 component, *accessor, attributes); |
| 6209 } | 6224 } |
| 6210 } else { | 6225 } else { |
| 6211 // If not, lookup a transition. | 6226 // If not, lookup a transition. |
| 6212 map()->LookupTransition(this, name, &result); | 6227 object->map()->LookupTransition(*object, *name, &result); |
| 6213 | 6228 |
| 6214 // If there is a transition, try to follow it. | 6229 // If there is a transition, try to follow it. |
| 6215 if (result.IsFound()) { | 6230 if (result.IsFound()) { |
| 6216 Map* target = result.GetTransitionTarget(); | 6231 Map* target = result.GetTransitionTarget(); |
| 6217 int descriptor_number = target->LastAdded(); | 6232 int descriptor_number = target->LastAdded(); |
| 6218 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) | 6233 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) |
| 6219 ->Equals(name)); | 6234 ->Equals(*name)); |
| 6220 return TryAccessorTransition( | 6235 return TryAccessorTransition(*object, target, descriptor_number, |
| 6221 this, target, descriptor_number, component, accessor, attributes); | 6236 component, *accessor, attributes); |
| 6222 } | 6237 } |
| 6223 } | 6238 } |
| 6224 | 6239 |
| 6225 // If there is no transition yet, add a transition to the a new accessor pair | 6240 // If there is no transition yet, add a transition to the a new accessor pair |
| 6226 // containing the accessor. | 6241 // containing the accessor. Allocate a new pair if there were no source |
| 6227 AccessorPair* accessors; | 6242 // accessors. Otherwise, copy the pair and modify the accessor. |
| 6228 MaybeObject* maybe_accessors; | 6243 Handle<AccessorPair> accessors = source_accessors != NULL |
| 6229 | 6244 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) |
| 6230 // Allocate a new pair if there were no source accessors. Otherwise, copy the | 6245 : isolate->factory()->NewAccessorPair(); |
| 6231 // pair and modify the accessor. | 6246 accessors->set(component, *accessor); |
| 6232 if (source_accessors != NULL) { | 6247 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), |
| 6233 maybe_accessors = source_accessors->Copy(); | 6248 name, accessors, attributes); |
| 6234 } else { | 6249 object->set_map(*new_map); |
| 6235 maybe_accessors = GetHeap()->AllocateAccessorPair(); | 6250 return true; |
| 6236 } | |
| 6237 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | |
| 6238 accessors->set(component, accessor); | |
| 6239 | |
| 6240 CallbacksDescriptor new_accessors_desc(name, accessors, attributes); | |
| 6241 | |
| 6242 Map* new_map; | |
| 6243 MaybeObject* maybe_new_map = | |
| 6244 map()->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION); | |
| 6245 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 6246 | |
| 6247 set_map(new_map); | |
| 6248 return this; | |
| 6249 } | 6251 } |
| 6250 | 6252 |
| 6251 | 6253 |
| 6252 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 6254 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
| 6253 Isolate* isolate = GetIsolate(); | 6255 Isolate* isolate = GetIsolate(); |
| 6254 Name* name = Name::cast(info->name()); | 6256 Name* name = Name::cast(info->name()); |
| 6255 // Check access rights if needed. | 6257 // Check access rights if needed. |
| 6256 if (IsAccessCheckNeeded() && | 6258 if (IsAccessCheckNeeded() && |
| 6257 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 6259 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 6258 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 6260 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6682 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6684 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 6683 DescriptorArray* new_descriptors; | 6685 DescriptorArray* new_descriptors; |
| 6684 MaybeObject* maybe_descriptors = | 6686 MaybeObject* maybe_descriptors = |
| 6685 descriptors->CopyUpTo(number_of_own_descriptors); | 6687 descriptors->CopyUpTo(number_of_own_descriptors); |
| 6686 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6688 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 6687 | 6689 |
| 6688 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6690 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); |
| 6689 } | 6691 } |
| 6690 | 6692 |
| 6691 | 6693 |
| 6694 Handle<Map> Map::Copy(Handle<Map> map) { |
| 6695 CALL_HEAP_FUNCTION(map->GetIsolate(), map->Copy(), Map); |
| 6696 } |
| 6697 |
| 6698 |
| 6692 MaybeObject* Map::Copy() { | 6699 MaybeObject* Map::Copy() { |
| 6693 DescriptorArray* descriptors = instance_descriptors(); | 6700 DescriptorArray* descriptors = instance_descriptors(); |
| 6694 DescriptorArray* new_descriptors; | 6701 DescriptorArray* new_descriptors; |
| 6695 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6702 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 6696 MaybeObject* maybe_descriptors = | 6703 MaybeObject* maybe_descriptors = |
| 6697 descriptors->CopyUpTo(number_of_own_descriptors); | 6704 descriptors->CopyUpTo(number_of_own_descriptors); |
| 6698 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6705 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 6699 | 6706 |
| 6700 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6707 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); |
| 6701 } | 6708 } |
| (...skipping 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7813 } | 7820 } |
| 7814 if (child_hash <= parent_hash) break; | 7821 if (child_hash <= parent_hash) break; |
| 7815 SwapSortedKeys(parent_index, child_index); | 7822 SwapSortedKeys(parent_index, child_index); |
| 7816 parent_index = child_index; | 7823 parent_index = child_index; |
| 7817 } | 7824 } |
| 7818 } | 7825 } |
| 7819 ASSERT(IsSortedNoDuplicates()); | 7826 ASSERT(IsSortedNoDuplicates()); |
| 7820 } | 7827 } |
| 7821 | 7828 |
| 7822 | 7829 |
| 7823 MaybeObject* AccessorPair::Copy() { | 7830 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) { |
| 7824 Heap* heap = GetHeap(); | 7831 Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair(); |
| 7825 AccessorPair* copy; | 7832 copy->set_getter(pair->getter()); |
| 7826 MaybeObject* maybe_copy = heap->AllocateAccessorPair(); | 7833 copy->set_setter(pair->setter()); |
| 7827 if (!maybe_copy->To(©)) return maybe_copy; | |
| 7828 | |
| 7829 copy->set_getter(getter()); | |
| 7830 copy->set_setter(setter()); | |
| 7831 return copy; | 7834 return copy; |
| 7832 } | 7835 } |
| 7833 | 7836 |
| 7834 | 7837 |
| 7835 Object* AccessorPair::GetComponent(AccessorComponent component) { | 7838 Object* AccessorPair::GetComponent(AccessorComponent component) { |
| 7836 Object* accessor = get(component); | 7839 Object* accessor = get(component); |
| 7837 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; | 7840 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; |
| 7838 } | 7841 } |
| 7839 | 7842 |
| 7840 | 7843 |
| (...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8855 AllocationSiteInfo* info = AllocationSiteInfo::cast( | 8858 AllocationSiteInfo* info = AllocationSiteInfo::cast( |
| 8856 reinterpret_cast<Object*>(ptr_end + 1)); | 8859 reinterpret_cast<Object*>(ptr_end + 1)); |
| 8857 return info; | 8860 return info; |
| 8858 } | 8861 } |
| 8859 } | 8862 } |
| 8860 } | 8863 } |
| 8861 return NULL; | 8864 return NULL; |
| 8862 } | 8865 } |
| 8863 | 8866 |
| 8864 | 8867 |
| 8865 bool AllocationSiteInfo::GetElementsKindPayload(ElementsKind* kind) { | |
| 8866 ASSERT(kind != NULL); | |
| 8867 if (payload()->IsCell()) { | |
| 8868 Cell* cell = Cell::cast(payload()); | |
| 8869 Object* cell_contents = cell->value(); | |
| 8870 if (cell_contents->IsSmi()) { | |
| 8871 *kind = static_cast<ElementsKind>( | |
| 8872 Smi::cast(cell_contents)->value()); | |
| 8873 return true; | |
| 8874 } | |
| 8875 } | |
| 8876 return false; | |
| 8877 } | |
| 8878 | |
| 8879 | |
| 8880 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { | 8868 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) { |
| 8881 // For array indexes mix the length into the hash as an array index could | 8869 // For array indexes mix the length into the hash as an array index could |
| 8882 // be zero. | 8870 // be zero. |
| 8883 ASSERT(length > 0); | 8871 ASSERT(length > 0); |
| 8884 ASSERT(length <= String::kMaxArrayIndexSize); | 8872 ASSERT(length <= String::kMaxArrayIndexSize); |
| 8885 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 8873 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
| 8886 (1 << String::kArrayIndexValueBits)); | 8874 (1 << String::kArrayIndexValueBits)); |
| 8887 | 8875 |
| 8888 value <<= String::kHashShift; | 8876 value <<= String::kHashShift; |
| 8889 value |= length << String::kArrayIndexHashLengthShift; | 8877 value |= length << String::kArrayIndexHashLengthShift; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9133 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 9121 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 9134 // Iterate over all fields in the body but take care in dealing with | 9122 // Iterate over all fields in the body but take care in dealing with |
| 9135 // the code entry. | 9123 // the code entry. |
| 9136 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 9124 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 9137 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 9125 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 9138 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 9126 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 9139 } | 9127 } |
| 9140 | 9128 |
| 9141 | 9129 |
| 9142 void JSFunction::MarkForLazyRecompilation() { | 9130 void JSFunction::MarkForLazyRecompilation() { |
| 9143 ASSERT(is_compiled() && !IsOptimized()); | 9131 ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); |
| 9132 ASSERT(!IsOptimized()); |
| 9144 ASSERT(shared()->allows_lazy_compilation() || | 9133 ASSERT(shared()->allows_lazy_compilation() || |
| 9145 code()->optimizable()); | 9134 code()->optimizable()); |
| 9146 set_code_no_write_barrier( | 9135 set_code_no_write_barrier( |
| 9147 GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile)); | 9136 GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile)); |
| 9148 // No write barrier required, since the builtin is part of the root set. | 9137 // No write barrier required, since the builtin is part of the root set. |
| 9149 } | 9138 } |
| 9150 | 9139 |
| 9151 | 9140 |
| 9152 void JSFunction::MarkForParallelRecompilation() { | 9141 void JSFunction::MarkForParallelRecompilation() { |
| 9153 ASSERT(is_compiled() && !IsOptimized()); | 9142 ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); |
| 9143 ASSERT(!IsOptimized()); |
| 9154 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9144 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9155 if (!FLAG_parallel_recompilation) { | 9145 if (!FLAG_parallel_recompilation) { |
| 9156 JSFunction::MarkForLazyRecompilation(); | 9146 JSFunction::MarkForLazyRecompilation(); |
| 9157 return; | 9147 return; |
| 9158 } | 9148 } |
| 9159 if (FLAG_trace_parallel_recompilation) { | 9149 if (FLAG_trace_parallel_recompilation) { |
| 9160 PrintF(" ** Marking "); | 9150 PrintF(" ** Marking "); |
| 9161 PrintName(); | 9151 PrintName(); |
| 9162 PrintF(" for parallel recompilation.\n"); | 9152 PrintF(" for parallel recompilation.\n"); |
| 9163 } | 9153 } |
| 9164 set_code_no_write_barrier( | 9154 set_code_no_write_barrier( |
| 9165 GetIsolate()->builtins()->builtin(Builtins::kParallelRecompile)); | 9155 GetIsolate()->builtins()->builtin(Builtins::kParallelRecompile)); |
| 9166 // No write barrier required, since the builtin is part of the root set. | 9156 // No write barrier required, since the builtin is part of the root set. |
| 9167 } | 9157 } |
| 9168 | 9158 |
| 9169 | 9159 |
| 9170 void JSFunction::MarkForInstallingRecompiledCode() { | 9160 void JSFunction::MarkForInstallingRecompiledCode() { |
| 9171 ASSERT(is_compiled() && !IsOptimized()); | 9161 // The debugger could have switched the builtin to lazy compile. |
| 9162 // In that case, simply carry on. It will be dealt with later. |
| 9163 ASSERT(!IsOptimized()); |
| 9172 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9164 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9173 ASSERT(FLAG_parallel_recompilation); | 9165 ASSERT(FLAG_parallel_recompilation); |
| 9174 set_code_no_write_barrier( | 9166 set_code_no_write_barrier( |
| 9175 GetIsolate()->builtins()->builtin(Builtins::kInstallRecompiledCode)); | 9167 GetIsolate()->builtins()->builtin(Builtins::kInstallRecompiledCode)); |
| 9176 // No write barrier required, since the builtin is part of the root set. | 9168 // No write barrier required, since the builtin is part of the root set. |
| 9177 } | 9169 } |
| 9178 | 9170 |
| 9179 | 9171 |
| 9180 void JSFunction::MarkInRecompileQueue() { | 9172 void JSFunction::MarkInRecompileQueue() { |
| 9181 ASSERT(is_compiled() && !IsOptimized()); | 9173 // We can only arrive here via the parallel-recompilation builtin. If |
| 9174 // break points were set, the code would point to the lazy-compile builtin. |
| 9175 ASSERT(!GetIsolate()->DebuggerHasBreakPoints()); |
| 9176 ASSERT(IsMarkedForParallelRecompilation() && !IsOptimized()); |
| 9182 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9177 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9183 ASSERT(FLAG_parallel_recompilation); | 9178 ASSERT(FLAG_parallel_recompilation); |
| 9184 if (FLAG_trace_parallel_recompilation) { | 9179 if (FLAG_trace_parallel_recompilation) { |
| 9185 PrintF(" ** Queueing "); | 9180 PrintF(" ** Queueing "); |
| 9186 PrintName(); | 9181 PrintName(); |
| 9187 PrintF(" for parallel recompilation.\n"); | 9182 PrintF(" for parallel recompilation.\n"); |
| 9188 } | 9183 } |
| 9189 set_code_no_write_barrier( | 9184 set_code_no_write_barrier( |
| 9190 GetIsolate()->builtins()->builtin(Builtins::kInRecompileQueue)); | 9185 GetIsolate()->builtins()->builtin(Builtins::kInRecompileQueue)); |
| 9191 // No write barrier required, since the builtin is part of the root set. | 9186 // No write barrier required, since the builtin is part of the root set. |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9389 if (!shared_info->script()->IsScript()) return false; | 9384 if (!shared_info->script()->IsScript()) return false; |
| 9390 if (shared_info->optimization_disabled()) return false; | 9385 if (shared_info->optimization_disabled()) return false; |
| 9391 Code* code = shared_info->code(); | 9386 Code* code = shared_info->code(); |
| 9392 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 9387 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
| 9393 // If we never ran this (unlikely) then lets try to optimize it. | 9388 // If we never ran this (unlikely) then lets try to optimize it. |
| 9394 if (code->kind() != Code::FUNCTION) return true; | 9389 if (code->kind() != Code::FUNCTION) return true; |
| 9395 return code->optimizable(); | 9390 return code->optimizable(); |
| 9396 } | 9391 } |
| 9397 | 9392 |
| 9398 | 9393 |
| 9394 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { |
| 9395 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->OptimizeAsPrototype()); |
| 9396 } |
| 9397 |
| 9398 |
| 9399 MaybeObject* JSObject::OptimizeAsPrototype() { | 9399 MaybeObject* JSObject::OptimizeAsPrototype() { |
| 9400 if (IsGlobalObject()) return this; | 9400 if (IsGlobalObject()) return this; |
| 9401 | 9401 |
| 9402 // Make sure prototypes are fast objects and their maps have the bit set | 9402 // Make sure prototypes are fast objects and their maps have the bit set |
| 9403 // so they remain fast. | 9403 // so they remain fast. |
| 9404 if (!HasFastProperties()) { | 9404 if (!HasFastProperties()) { |
| 9405 MaybeObject* new_proto = TransformToFastProperties(0); | 9405 MaybeObject* new_proto = TransformToFastProperties(0); |
| 9406 if (new_proto->IsFailure()) return new_proto; | 9406 if (new_proto->IsFailure()) return new_proto; |
| 9407 ASSERT(new_proto == this); | 9407 ASSERT(new_proto == this); |
| 9408 } | 9408 } |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9956 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 9956 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && |
| 9957 rinfo->IsPatchedReturnSequence()) || | 9957 rinfo->IsPatchedReturnSequence()) || |
| 9958 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 9958 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 9959 rinfo->IsPatchedDebugBreakSlotSequence())); | 9959 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 9960 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 9960 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 9961 Object* old_target = target; | 9961 Object* old_target = target; |
| 9962 VisitPointer(&target); | 9962 VisitPointer(&target); |
| 9963 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 9963 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 9964 } | 9964 } |
| 9965 | 9965 |
| 9966 |
| 9966 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { | 9967 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { |
| 9967 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 9968 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| 9968 VisitPointer(rinfo->target_object_address()); | 9969 VisitPointer(rinfo->target_object_address()); |
| 9969 } | 9970 } |
| 9970 | 9971 |
| 9972 |
| 9971 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { | 9973 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { |
| 9972 Address* p = rinfo->target_reference_address(); | 9974 Address* p = rinfo->target_reference_address(); |
| 9973 VisitExternalReferences(p, p + 1); | 9975 VisitExternalReferences(p, p + 1); |
| 9974 } | 9976 } |
| 9975 | 9977 |
| 9978 |
| 9976 byte Code::compare_nil_state() { | 9979 byte Code::compare_nil_state() { |
| 9977 ASSERT(is_compare_nil_ic_stub()); | 9980 ASSERT(is_compare_nil_ic_stub()); |
| 9978 return CompareNilICStub::ExtractTypesFromExtraICState( | 9981 return CompareNilICStub::ExtractTypesFromExtraICState( |
| 9979 extended_extra_ic_state()); | 9982 extended_extra_ic_state()); |
| 9980 } | 9983 } |
| 9981 | 9984 |
| 9985 |
| 9982 byte Code::compare_nil_value() { | 9986 byte Code::compare_nil_value() { |
| 9983 ASSERT(is_compare_nil_ic_stub()); | 9987 ASSERT(is_compare_nil_ic_stub()); |
| 9984 return CompareNilICStub::ExtractNilValueFromExtraICState( | 9988 return CompareNilICStub::ExtractNilValueFromExtraICState( |
| 9985 extended_extra_ic_state()); | 9989 extended_extra_ic_state()); |
| 9986 } | 9990 } |
| 9987 | 9991 |
| 9988 | 9992 |
| 9989 void Code::InvalidateRelocation() { | 9993 void Code::InvalidateRelocation() { |
| 9990 set_relocation_info(GetHeap()->empty_byte_array()); | 9994 set_relocation_info(GetHeap()->empty_byte_array()); |
| 9991 } | 9995 } |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10243 | 10247 |
| 10244 | 10248 |
| 10245 void Code::ClearTypeFeedbackCells(Heap* heap) { | 10249 void Code::ClearTypeFeedbackCells(Heap* heap) { |
| 10246 if (kind() != FUNCTION) return; | 10250 if (kind() != FUNCTION) return; |
| 10247 Object* raw_info = type_feedback_info(); | 10251 Object* raw_info = type_feedback_info(); |
| 10248 if (raw_info->IsTypeFeedbackInfo()) { | 10252 if (raw_info->IsTypeFeedbackInfo()) { |
| 10249 TypeFeedbackCells* type_feedback_cells = | 10253 TypeFeedbackCells* type_feedback_cells = |
| 10250 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells(); | 10254 TypeFeedbackInfo::cast(raw_info)->type_feedback_cells(); |
| 10251 for (int i = 0; i < type_feedback_cells->CellCount(); i++) { | 10255 for (int i = 0; i < type_feedback_cells->CellCount(); i++) { |
| 10252 Cell* cell = type_feedback_cells->GetCell(i); | 10256 Cell* cell = type_feedback_cells->GetCell(i); |
| 10253 cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap)); | 10257 // Don't clear AllocationSites |
| 10258 Object* value = cell->value(); |
| 10259 if (value == NULL || !value->IsAllocationSite()) { |
| 10260 cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap)); |
| 10261 } |
| 10254 } | 10262 } |
| 10255 } | 10263 } |
| 10256 } | 10264 } |
| 10257 | 10265 |
| 10258 | 10266 |
| 10259 bool Code::allowed_in_shared_map_code_cache() { | 10267 bool Code::allowed_in_shared_map_code_cache() { |
| 10260 return is_keyed_load_stub() || is_keyed_store_stub() || | 10268 return is_keyed_load_stub() || is_keyed_store_stub() || |
| 10261 (is_compare_ic_stub() && | 10269 (is_compare_ic_stub() && |
| 10262 ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT); | 10270 ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT); |
| 10263 } | 10271 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10374 GetIsolate(), info->target_address(), Deoptimizer::SOFT))) { | 10382 GetIsolate(), info->target_address(), Deoptimizer::SOFT))) { |
| 10375 CHECK(RelocInfo::IsRuntimeEntry(info->rmode())); | 10383 CHECK(RelocInfo::IsRuntimeEntry(info->rmode())); |
| 10376 PrintF(" %s\n", last_comment); | 10384 PrintF(" %s\n", last_comment); |
| 10377 return; | 10385 return; |
| 10378 } | 10386 } |
| 10379 } | 10387 } |
| 10380 } | 10388 } |
| 10381 } | 10389 } |
| 10382 | 10390 |
| 10383 | 10391 |
| 10392 bool Code::CanDeoptAt(Address pc) { |
| 10393 DeoptimizationInputData* deopt_data = |
| 10394 DeoptimizationInputData::cast(deoptimization_data()); |
| 10395 Address code_start_address = instruction_start(); |
| 10396 for (int i = 0; i < deopt_data->DeoptCount(); i++) { |
| 10397 if (deopt_data->Pc(i)->value() == -1) continue; |
| 10398 Address address = code_start_address + deopt_data->Pc(i)->value(); |
| 10399 if (address == pc) return true; |
| 10400 } |
| 10401 return false; |
| 10402 } |
| 10403 |
| 10404 |
| 10384 // Identify kind of code. | 10405 // Identify kind of code. |
| 10385 const char* Code::Kind2String(Kind kind) { | 10406 const char* Code::Kind2String(Kind kind) { |
| 10386 switch (kind) { | 10407 switch (kind) { |
| 10387 #define CASE(name) case name: return #name; | 10408 #define CASE(name) case name: return #name; |
| 10388 CODE_KIND_LIST(CASE) | 10409 CODE_KIND_LIST(CASE) |
| 10389 #undef CASE | 10410 #undef CASE |
| 10390 case NUMBER_OF_KINDS: break; | 10411 case NUMBER_OF_KINDS: break; |
| 10391 } | 10412 } |
| 10392 UNREACHABLE(); | 10413 UNREACHABLE(); |
| 10393 return NULL; | 10414 return NULL; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10592 case INTERCEPTOR: return "INTERCEPTOR"; | 10613 case INTERCEPTOR: return "INTERCEPTOR"; |
| 10593 case MAP_TRANSITION: return "MAP_TRANSITION"; | 10614 case MAP_TRANSITION: return "MAP_TRANSITION"; |
| 10594 case NONEXISTENT: return "NONEXISTENT"; | 10615 case NONEXISTENT: return "NONEXISTENT"; |
| 10595 } | 10616 } |
| 10596 UNREACHABLE(); // keep the compiler happy | 10617 UNREACHABLE(); // keep the compiler happy |
| 10597 return NULL; | 10618 return NULL; |
| 10598 } | 10619 } |
| 10599 | 10620 |
| 10600 | 10621 |
| 10601 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { | 10622 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
| 10623 PrintF(out, "extra_ic_state = "); |
| 10602 const char* name = NULL; | 10624 const char* name = NULL; |
| 10603 switch (kind) { | 10625 switch (kind) { |
| 10604 case CALL_IC: | 10626 case CALL_IC: |
| 10605 if (extra == STRING_INDEX_OUT_OF_BOUNDS) { | 10627 if (extra == STRING_INDEX_OUT_OF_BOUNDS) { |
| 10606 name = "STRING_INDEX_OUT_OF_BOUNDS"; | 10628 name = "STRING_INDEX_OUT_OF_BOUNDS"; |
| 10607 } | 10629 } |
| 10608 break; | 10630 break; |
| 10609 case STORE_IC: | 10631 case STORE_IC: |
| 10610 case KEYED_STORE_IC: | 10632 case KEYED_STORE_IC: |
| 10611 if (extra == kStrictMode) { | 10633 if (extra == kStrictMode) { |
| 10612 name = "STRICT"; | 10634 name = "STRICT"; |
| 10613 } | 10635 } |
| 10614 break; | 10636 break; |
| 10615 default: | 10637 default: |
| 10616 break; | 10638 break; |
| 10617 } | 10639 } |
| 10618 if (name != NULL) { | 10640 if (name != NULL) { |
| 10619 PrintF(out, "extra_ic_state = %s\n", name); | 10641 PrintF(out, "%s\n", name); |
| 10620 } else { | 10642 } else { |
| 10621 PrintF(out, "extra_ic_state = %d\n", extra); | 10643 PrintF(out, "%d\n", extra); |
| 10622 } | 10644 } |
| 10623 } | 10645 } |
| 10624 | 10646 |
| 10625 | 10647 |
| 10626 void Code::Disassemble(const char* name, FILE* out) { | 10648 void Code::Disassemble(const char* name, FILE* out) { |
| 10627 PrintF(out, "kind = %s\n", Kind2String(kind())); | 10649 PrintF(out, "kind = %s\n", Kind2String(kind())); |
| 10628 if (is_inline_cache_stub()) { | 10650 if (is_inline_cache_stub()) { |
| 10629 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); | 10651 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); |
| 10630 PrintExtraICState(out, kind(), extra_ic_state()); | 10652 PrintExtraICState(out, kind(), needs_extended_extra_ic_state(kind()) ? |
| 10653 extended_extra_ic_state() : extra_ic_state()); |
| 10631 if (ic_state() == MONOMORPHIC) { | 10654 if (ic_state() == MONOMORPHIC) { |
| 10632 PrintF(out, "type = %s\n", StubType2String(type())); | 10655 PrintF(out, "type = %s\n", StubType2String(type())); |
| 10633 } | 10656 } |
| 10634 if (is_call_stub() || is_keyed_call_stub()) { | 10657 if (is_call_stub() || is_keyed_call_stub()) { |
| 10635 PrintF(out, "argc = %d\n", arguments_count()); | 10658 PrintF(out, "argc = %d\n", arguments_count()); |
| 10636 } | 10659 } |
| 10637 if (is_compare_ic_stub()) { | 10660 if (is_compare_ic_stub()) { |
| 10638 ASSERT(major_key() == CodeStub::CompareIC); | 10661 ASSERT(major_key() == CodeStub::CompareIC); |
| 10639 CompareIC::State left_state, right_state, handler_state; | 10662 CompareIC::State left_state, right_state, handler_state; |
| 10640 Token::Value op; | 10663 Token::Value op; |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11001 isolate->factory()->NewNumberFromUint(delete_count), | 11024 isolate->factory()->NewNumberFromUint(delete_count), |
| 11002 NONE, kNonStrictMode); | 11025 NONE, kNonStrictMode); |
| 11003 } | 11026 } |
| 11004 | 11027 |
| 11005 EnqueueSpliceRecord(self, index, deleted, add_count); | 11028 EnqueueSpliceRecord(self, index, deleted, add_count); |
| 11006 | 11029 |
| 11007 return *hresult; | 11030 return *hresult; |
| 11008 } | 11031 } |
| 11009 | 11032 |
| 11010 | 11033 |
| 11011 Map* Map::GetPrototypeTransition(Object* prototype) { | 11034 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map, |
| 11012 FixedArray* cache = GetPrototypeTransitions(); | 11035 Handle<Object> prototype) { |
| 11013 int number_of_transitions = NumberOfProtoTransitions(); | 11036 FixedArray* cache = map->GetPrototypeTransitions(); |
| 11037 int number_of_transitions = map->NumberOfProtoTransitions(); |
| 11014 const int proto_offset = | 11038 const int proto_offset = |
| 11015 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 11039 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
| 11016 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 11040 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
| 11017 const int step = kProtoTransitionElementsPerEntry; | 11041 const int step = kProtoTransitionElementsPerEntry; |
| 11018 for (int i = 0; i < number_of_transitions; i++) { | 11042 for (int i = 0; i < number_of_transitions; i++) { |
| 11019 if (cache->get(proto_offset + i * step) == prototype) { | 11043 if (cache->get(proto_offset + i * step) == *prototype) { |
| 11020 Object* map = cache->get(map_offset + i * step); | 11044 Object* result = cache->get(map_offset + i * step); |
| 11021 return Map::cast(map); | 11045 return Handle<Map>(Map::cast(result)); |
| 11022 } | 11046 } |
| 11023 } | 11047 } |
| 11024 return NULL; | 11048 return Handle<Map>(); |
| 11025 } | 11049 } |
| 11026 | 11050 |
| 11027 | 11051 |
| 11028 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { | 11052 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
| 11029 ASSERT(map->IsMap()); | 11053 Handle<Object> prototype, |
| 11030 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); | 11054 Handle<Map> target_map) { |
| 11055 ASSERT(target_map->IsMap()); |
| 11056 ASSERT(HeapObject::cast(*prototype)->map()->IsMap()); |
| 11031 // Don't cache prototype transition if this map is shared. | 11057 // Don't cache prototype transition if this map is shared. |
| 11032 if (is_shared() || !FLAG_cache_prototype_transitions) return this; | 11058 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; |
| 11033 | |
| 11034 FixedArray* cache = GetPrototypeTransitions(); | |
| 11035 | 11059 |
| 11036 const int step = kProtoTransitionElementsPerEntry; | 11060 const int step = kProtoTransitionElementsPerEntry; |
| 11037 const int header = kProtoTransitionHeaderSize; | 11061 const int header = kProtoTransitionHeaderSize; |
| 11038 | 11062 |
| 11063 Handle<FixedArray> cache(map->GetPrototypeTransitions()); |
| 11039 int capacity = (cache->length() - header) / step; | 11064 int capacity = (cache->length() - header) / step; |
| 11040 | 11065 int transitions = map->NumberOfProtoTransitions() + 1; |
| 11041 int transitions = NumberOfProtoTransitions() + 1; | |
| 11042 | 11066 |
| 11043 if (transitions > capacity) { | 11067 if (transitions > capacity) { |
| 11044 if (capacity > kMaxCachedPrototypeTransitions) return this; | 11068 if (capacity > kMaxCachedPrototypeTransitions) return map; |
| 11045 | 11069 |
| 11046 FixedArray* new_cache; | |
| 11047 // Grow array by factor 2 over and above what we need. | 11070 // Grow array by factor 2 over and above what we need. |
| 11048 { MaybeObject* maybe_cache = | 11071 Factory* factory = map->GetIsolate()->factory(); |
| 11049 GetHeap()->AllocateFixedArray(transitions * 2 * step + header); | 11072 cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header); |
| 11050 if (!maybe_cache->To(&new_cache)) return maybe_cache; | |
| 11051 } | |
| 11052 | 11073 |
| 11053 for (int i = 0; i < capacity * step; i++) { | 11074 CALL_AND_RETRY_OR_DIE(map->GetIsolate(), |
| 11054 new_cache->set(i + header, cache->get(i + header)); | 11075 map->SetPrototypeTransitions(*cache), |
| 11055 } | 11076 break, |
| 11056 cache = new_cache; | 11077 return Handle<Map>()); |
| 11057 MaybeObject* set_result = SetPrototypeTransitions(cache); | |
| 11058 if (set_result->IsFailure()) return set_result; | |
| 11059 } | 11078 } |
| 11060 | 11079 |
| 11061 int last = transitions - 1; | 11080 // Reload number of transitions as GC might shrink them. |
| 11081 int last = map->NumberOfProtoTransitions(); |
| 11082 int entry = header + last * step; |
| 11062 | 11083 |
| 11063 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype); | 11084 cache->set(entry + kProtoTransitionPrototypeOffset, *prototype); |
| 11064 cache->set(header + last * step + kProtoTransitionMapOffset, map); | 11085 cache->set(entry + kProtoTransitionMapOffset, *target_map); |
| 11065 SetNumberOfProtoTransitions(transitions); | 11086 map->SetNumberOfProtoTransitions(transitions); |
| 11066 | 11087 |
| 11067 return cache; | 11088 return map; |
| 11068 } | 11089 } |
| 11069 | 11090 |
| 11070 | 11091 |
| 11071 void Map::ZapTransitions() { | 11092 void Map::ZapTransitions() { |
| 11072 TransitionArray* transition_array = transitions(); | 11093 TransitionArray* transition_array = transitions(); |
| 11073 // TODO(mstarzinger): Temporarily use a slower version instead of the faster | 11094 // TODO(mstarzinger): Temporarily use a slower version instead of the faster |
| 11074 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer. | 11095 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer. |
| 11075 Object** data = transition_array->data_start(); | 11096 Object** data = transition_array->data_start(); |
| 11076 Object* the_hole = GetHeap()->the_hole_value(); | 11097 Object* the_hole = GetHeap()->the_hole_value(); |
| 11077 int length = transition_array->length(); | 11098 int length = transition_array->length(); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11280 int removed = end - start; | 11301 int removed = end - start; |
| 11281 for (int i = code_entries - removed; i < code_entries; i++) { | 11302 for (int i = code_entries - removed; i < code_entries; i++) { |
| 11282 clear_at(i); | 11303 clear_at(i); |
| 11283 } | 11304 } |
| 11284 set_number_of_entries(group, 0); | 11305 set_number_of_entries(group, 0); |
| 11285 DeoptimizeDependentCodeFilter filter; | 11306 DeoptimizeDependentCodeFilter filter; |
| 11286 Deoptimizer::DeoptimizeAllFunctionsWith(isolate, &filter); | 11307 Deoptimizer::DeoptimizeAllFunctionsWith(isolate, &filter); |
| 11287 } | 11308 } |
| 11288 | 11309 |
| 11289 | 11310 |
| 11290 MaybeObject* JSReceiver::SetPrototype(Object* value, | 11311 Handle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
| 11312 Handle<Object> value, |
| 11291 bool skip_hidden_prototypes) { | 11313 bool skip_hidden_prototypes) { |
| 11292 #ifdef DEBUG | 11314 #ifdef DEBUG |
| 11293 int size = Size(); | 11315 int size = object->Size(); |
| 11294 #endif | 11316 #endif |
| 11295 | 11317 |
| 11296 Isolate* isolate = GetIsolate(); | 11318 Isolate* isolate = object->GetIsolate(); |
| 11297 Heap* heap = isolate->heap(); | 11319 Heap* heap = isolate->heap(); |
| 11298 // Silently ignore the change if value is not a JSObject or null. | 11320 // Silently ignore the change if value is not a JSObject or null. |
| 11299 // SpiderMonkey behaves this way. | 11321 // SpiderMonkey behaves this way. |
| 11300 if (!value->IsJSReceiver() && !value->IsNull()) return value; | 11322 if (!value->IsJSReceiver() && !value->IsNull()) return value; |
| 11301 | 11323 |
| 11302 // From 8.6.2 Object Internal Methods | 11324 // From 8.6.2 Object Internal Methods |
| 11303 // ... | 11325 // ... |
| 11304 // In addition, if [[Extensible]] is false the value of the [[Class]] and | 11326 // In addition, if [[Extensible]] is false the value of the [[Class]] and |
| 11305 // [[Prototype]] internal properties of the object may not be modified. | 11327 // [[Prototype]] internal properties of the object may not be modified. |
| 11306 // ... | 11328 // ... |
| 11307 // Implementation specific extensions that modify [[Class]], [[Prototype]] | 11329 // Implementation specific extensions that modify [[Class]], [[Prototype]] |
| 11308 // or [[Extensible]] must not violate the invariants defined in the preceding | 11330 // or [[Extensible]] must not violate the invariants defined in the preceding |
| 11309 // paragraph. | 11331 // paragraph. |
| 11310 if (!this->map()->is_extensible()) { | 11332 if (!object->map()->is_extensible()) { |
| 11311 HandleScope scope(isolate); | 11333 Handle<Object> args[] = { object }; |
| 11312 Handle<Object> handle(this, isolate); | 11334 Handle<Object> error = isolate->factory()->NewTypeError( |
| 11313 return isolate->Throw( | 11335 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); |
| 11314 *isolate->factory()->NewTypeError("non_extensible_proto", | 11336 isolate->Throw(*error); |
| 11315 HandleVector<Object>(&handle, 1))); | 11337 return Handle<Object>(); |
| 11316 } | 11338 } |
| 11317 | 11339 |
| 11318 // Before we can set the prototype we need to be sure | 11340 // Before we can set the prototype we need to be sure |
| 11319 // prototype cycles are prevented. | 11341 // prototype cycles are prevented. |
| 11320 // It is sufficient to validate that the receiver is not in the new prototype | 11342 // It is sufficient to validate that the receiver is not in the new prototype |
| 11321 // chain. | 11343 // chain. |
| 11322 for (Object* pt = value; | 11344 for (Object* pt = *value; |
| 11323 pt != heap->null_value(); | 11345 pt != heap->null_value(); |
| 11324 pt = pt->GetPrototype(isolate)) { | 11346 pt = pt->GetPrototype(isolate)) { |
| 11325 if (JSReceiver::cast(pt) == this) { | 11347 if (JSReceiver::cast(pt) == *object) { |
| 11326 // Cycle detected. | 11348 // Cycle detected. |
| 11327 HandleScope scope(isolate); | 11349 Handle<Object> error = isolate->factory()->NewError( |
| 11328 return isolate->Throw( | 11350 "cyclic_proto", HandleVector<Object>(NULL, 0)); |
| 11329 *isolate->factory()->NewError("cyclic_proto", | 11351 isolate->Throw(*error); |
| 11330 HandleVector<Object>(NULL, 0))); | 11352 return Handle<Object>(); |
| 11331 } | 11353 } |
| 11332 } | 11354 } |
| 11333 | 11355 |
| 11334 JSReceiver* real_receiver = this; | 11356 Handle<JSObject> real_receiver = object; |
| 11335 | 11357 |
| 11336 if (skip_hidden_prototypes) { | 11358 if (skip_hidden_prototypes) { |
| 11337 // Find the first object in the chain whose prototype object is not | 11359 // Find the first object in the chain whose prototype object is not |
| 11338 // hidden and set the new prototype on that object. | 11360 // hidden and set the new prototype on that object. |
| 11339 Object* current_proto = real_receiver->GetPrototype(); | 11361 Object* current_proto = real_receiver->GetPrototype(); |
| 11340 while (current_proto->IsJSObject() && | 11362 while (current_proto->IsJSObject() && |
| 11341 JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) { | 11363 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
| 11342 real_receiver = JSReceiver::cast(current_proto); | 11364 real_receiver = handle(JSObject::cast(current_proto), isolate); |
| 11343 current_proto = current_proto->GetPrototype(isolate); | 11365 current_proto = current_proto->GetPrototype(isolate); |
| 11344 } | 11366 } |
| 11345 } | 11367 } |
| 11346 | 11368 |
| 11347 // Set the new prototype of the object. | 11369 // Set the new prototype of the object. |
| 11348 Map* map = real_receiver->map(); | 11370 Handle<Map> map(real_receiver->map()); |
| 11349 | 11371 |
| 11350 // Nothing to do if prototype is already set. | 11372 // Nothing to do if prototype is already set. |
| 11351 if (map->prototype() == value) return value; | 11373 if (map->prototype() == *value) return value; |
| 11352 | 11374 |
| 11353 if (value->IsJSObject()) { | 11375 if (value->IsJSObject()) { |
| 11354 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | 11376 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 11355 if (ok->IsFailure()) return ok; | |
| 11356 } | 11377 } |
| 11357 | 11378 |
| 11358 Map* new_map = map->GetPrototypeTransition(value); | 11379 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); |
| 11359 if (new_map == NULL) { | 11380 if (new_map.is_null()) { |
| 11360 MaybeObject* maybe_new_map = map->Copy(); | 11381 new_map = Map::Copy(map); |
| 11361 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 11382 Map::PutPrototypeTransition(map, value, new_map); |
| 11362 | 11383 new_map->set_prototype(*value); |
| 11363 MaybeObject* maybe_new_cache = | |
| 11364 map->PutPrototypeTransition(value, new_map); | |
| 11365 if (maybe_new_cache->IsFailure()) return maybe_new_cache; | |
| 11366 | |
| 11367 new_map->set_prototype(value); | |
| 11368 } | 11384 } |
| 11369 ASSERT(new_map->prototype() == value); | 11385 ASSERT(new_map->prototype() == *value); |
| 11370 real_receiver->set_map(new_map); | 11386 real_receiver->set_map(*new_map); |
| 11371 | 11387 |
| 11372 heap->ClearInstanceofCache(); | 11388 heap->ClearInstanceofCache(); |
| 11373 ASSERT(size == Size()); | 11389 ASSERT(size == object->Size()); |
| 11374 return value; | 11390 return value; |
| 11375 } | 11391 } |
| 11376 | 11392 |
| 11377 | 11393 |
| 11378 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 11394 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
| 11379 uint32_t first_arg, | 11395 uint32_t first_arg, |
| 11380 uint32_t arg_count, | 11396 uint32_t arg_count, |
| 11381 EnsureElementsMode mode) { | 11397 EnsureElementsMode mode) { |
| 11382 // Elements in |Arguments| are ordered backwards (because they're on the | 11398 // Elements in |Arguments| are ordered backwards (because they're on the |
| 11383 // stack), but the method that's called here iterates over them in forward | 11399 // stack), but the method that's called here iterates over them in forward |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11700 check_prototype); | 11716 check_prototype); |
| 11701 } | 11717 } |
| 11702 } | 11718 } |
| 11703 // Convert to fast double elements if appropriate. | 11719 // Convert to fast double elements if appropriate. |
| 11704 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { | 11720 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
| 11705 // Consider fixing the boilerplate as well if we have one. | 11721 // Consider fixing the boilerplate as well if we have one. |
| 11706 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) | 11722 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) |
| 11707 ? FAST_HOLEY_DOUBLE_ELEMENTS | 11723 ? FAST_HOLEY_DOUBLE_ELEMENTS |
| 11708 : FAST_DOUBLE_ELEMENTS; | 11724 : FAST_DOUBLE_ELEMENTS; |
| 11709 | 11725 |
| 11710 MaybeObject* maybe_failure = UpdateAllocationSiteInfo(to_kind); | 11726 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| 11711 if (maybe_failure->IsFailure()) return maybe_failure; | 11727 if (maybe_failure->IsFailure()) return maybe_failure; |
| 11712 | 11728 |
| 11713 MaybeObject* maybe = | 11729 MaybeObject* maybe = |
| 11714 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 11730 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
| 11715 if (maybe->IsFailure()) return maybe; | 11731 if (maybe->IsFailure()) return maybe; |
| 11716 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 11732 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
| 11717 ValidateElements(); | 11733 ValidateElements(); |
| 11718 return value; | 11734 return value; |
| 11719 } | 11735 } |
| 11720 // Change elements kind from Smi-only to generic FAST if necessary. | 11736 // Change elements kind from Smi-only to generic FAST if necessary. |
| 11721 if (HasFastSmiElements() && !value->IsSmi()) { | 11737 if (HasFastSmiElements() && !value->IsSmi()) { |
| 11722 Map* new_map; | 11738 Map* new_map; |
| 11723 ElementsKind kind = HasFastHoleyElements() | 11739 ElementsKind kind = HasFastHoleyElements() |
| 11724 ? FAST_HOLEY_ELEMENTS | 11740 ? FAST_HOLEY_ELEMENTS |
| 11725 : FAST_ELEMENTS; | 11741 : FAST_ELEMENTS; |
| 11726 | 11742 |
| 11727 MaybeObject* maybe_failure = UpdateAllocationSiteInfo(kind); | 11743 MaybeObject* maybe_failure = UpdateAllocationSite(kind); |
| 11728 if (maybe_failure->IsFailure()) return maybe_failure; | 11744 if (maybe_failure->IsFailure()) return maybe_failure; |
| 11729 | 11745 |
| 11730 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 11746 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
| 11731 kind); | 11747 kind); |
| 11732 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 11748 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 11733 | 11749 |
| 11734 set_map(new_map); | 11750 set_map(new_map); |
| 11735 } | 11751 } |
| 11736 // Increase backing store capacity if that's been decided previously. | 11752 // Increase backing store capacity if that's been decided previously. |
| 11737 if (new_capacity != capacity) { | 11753 if (new_capacity != capacity) { |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12280 | 12296 |
| 12281 | 12297 |
| 12282 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, | 12298 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, |
| 12283 ElementsKind to_kind) { | 12299 ElementsKind to_kind) { |
| 12284 CALL_HEAP_FUNCTION(object->GetIsolate(), | 12300 CALL_HEAP_FUNCTION(object->GetIsolate(), |
| 12285 object->TransitionElementsKind(to_kind), | 12301 object->TransitionElementsKind(to_kind), |
| 12286 Object); | 12302 Object); |
| 12287 } | 12303 } |
| 12288 | 12304 |
| 12289 | 12305 |
| 12290 MaybeObject* JSObject::UpdateAllocationSiteInfo(ElementsKind to_kind) { | 12306 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| 12291 if (!FLAG_track_allocation_sites || !IsJSArray()) { | 12307 if (!FLAG_track_allocation_sites || !IsJSArray()) { |
| 12292 return this; | 12308 return this; |
| 12293 } | 12309 } |
| 12294 | 12310 |
| 12295 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(this); | 12311 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(this); |
| 12296 if (info == NULL) { | 12312 if (info == NULL || !info->IsValid()) { |
| 12297 return this; | 12313 return this; |
| 12298 } | 12314 } |
| 12299 | 12315 |
| 12300 if (info->payload()->IsJSArray()) { | 12316 // Walk through to the Allocation Site |
| 12301 JSArray* payload = JSArray::cast(info->payload()); | 12317 AllocationSite* site = info->GetAllocationSite(); |
| 12318 if (site->IsLiteralSite()) { |
| 12319 JSArray* payload = JSArray::cast(site->payload()); |
| 12302 ElementsKind kind = payload->GetElementsKind(); | 12320 ElementsKind kind = payload->GetElementsKind(); |
| 12303 if (AllocationSiteInfo::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { | 12321 if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 12304 // If the array is huge, it's not likely to be defined in a local | 12322 // If the array is huge, it's not likely to be defined in a local |
| 12305 // function, so we shouldn't make new instances of it very often. | 12323 // function, so we shouldn't make new instances of it very often. |
| 12306 uint32_t length = 0; | 12324 uint32_t length = 0; |
| 12307 CHECK(payload->length()->ToArrayIndex(&length)); | 12325 CHECK(payload->length()->ToArrayIndex(&length)); |
| 12308 if (length <= AllocationSiteInfo::kMaximumArrayBytesToPretransition) { | 12326 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { |
| 12309 if (FLAG_trace_track_allocation_sites) { | 12327 if (FLAG_trace_track_allocation_sites) { |
| 12310 PrintF( | 12328 PrintF( |
| 12311 "AllocationSiteInfo: JSArray %p boilerplate updated %s->%s\n", | 12329 "AllocationSite: JSArray %p boilerplate updated %s->%s\n", |
| 12312 reinterpret_cast<void*>(this), | 12330 reinterpret_cast<void*>(this), |
| 12313 ElementsKindToString(kind), | 12331 ElementsKindToString(kind), |
| 12314 ElementsKindToString(to_kind)); | 12332 ElementsKindToString(to_kind)); |
| 12315 } | 12333 } |
| 12316 return payload->TransitionElementsKind(to_kind); | 12334 return payload->TransitionElementsKind(to_kind); |
| 12317 } | 12335 } |
| 12318 } | 12336 } |
| 12319 } else if (info->payload()->IsCell()) { | 12337 } else { |
| 12320 Cell* cell = Cell::cast(info->payload()); | 12338 ElementsKind kind = site->GetElementsKindPayload(); |
| 12321 Object* cell_contents = cell->value(); | 12339 if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 12322 if (cell_contents->IsSmi()) { | 12340 if (FLAG_trace_track_allocation_sites) { |
| 12323 ElementsKind kind = static_cast<ElementsKind>( | 12341 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", |
| 12324 Smi::cast(cell_contents)->value()); | 12342 reinterpret_cast<void*>(this), |
| 12325 if (AllocationSiteInfo::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { | 12343 ElementsKindToString(kind), |
| 12326 if (FLAG_trace_track_allocation_sites) { | 12344 ElementsKindToString(to_kind)); |
| 12327 PrintF("AllocationSiteInfo: JSArray %p info updated %s->%s\n", | |
| 12328 reinterpret_cast<void*>(this), | |
| 12329 ElementsKindToString(kind), | |
| 12330 ElementsKindToString(to_kind)); | |
| 12331 } | |
| 12332 cell->set_value(Smi::FromInt(to_kind)); | |
| 12333 } | 12345 } |
| 12346 site->set_payload(Smi::FromInt(to_kind)); |
| 12334 } | 12347 } |
| 12335 } | 12348 } |
| 12336 return this; | 12349 return this; |
| 12337 } | 12350 } |
| 12338 | 12351 |
| 12339 | 12352 |
| 12340 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 12353 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
| 12341 ASSERT(!map()->is_observed()); | 12354 ASSERT(!map()->is_observed()); |
| 12342 ElementsKind from_kind = map()->elements_kind(); | 12355 ElementsKind from_kind = map()->elements_kind(); |
| 12343 | 12356 |
| 12344 if (IsFastHoleyElementsKind(from_kind)) { | 12357 if (IsFastHoleyElementsKind(from_kind)) { |
| 12345 to_kind = GetHoleyElementsKind(to_kind); | 12358 to_kind = GetHoleyElementsKind(to_kind); |
| 12346 } | 12359 } |
| 12347 | 12360 |
| 12348 if (from_kind == to_kind) return this; | 12361 if (from_kind == to_kind) return this; |
| 12349 | 12362 |
| 12350 MaybeObject* maybe_failure = UpdateAllocationSiteInfo(to_kind); | 12363 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| 12351 if (maybe_failure->IsFailure()) return maybe_failure; | 12364 if (maybe_failure->IsFailure()) return maybe_failure; |
| 12352 | 12365 |
| 12353 Isolate* isolate = GetIsolate(); | 12366 Isolate* isolate = GetIsolate(); |
| 12354 if (elements() == isolate->heap()->empty_fixed_array() || | 12367 if (elements() == isolate->heap()->empty_fixed_array() || |
| 12355 (IsFastSmiOrObjectElementsKind(from_kind) && | 12368 (IsFastSmiOrObjectElementsKind(from_kind) && |
| 12356 IsFastSmiOrObjectElementsKind(to_kind)) || | 12369 IsFastSmiOrObjectElementsKind(to_kind)) || |
| 12357 (from_kind == FAST_DOUBLE_ELEMENTS && | 12370 (from_kind == FAST_DOUBLE_ELEMENTS && |
| 12358 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 12371 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
| 12359 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 12372 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
| 12360 // No change is needed to the elements() buffer, the transition | 12373 // No change is needed to the elements() buffer, the transition |
| (...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13288 } | 13301 } |
| 13289 | 13302 |
| 13290 static uint32_t RegExpHash(String* string, Smi* flags) { | 13303 static uint32_t RegExpHash(String* string, Smi* flags) { |
| 13291 return string->Hash() + flags->value(); | 13304 return string->Hash() + flags->value(); |
| 13292 } | 13305 } |
| 13293 | 13306 |
| 13294 String* string_; | 13307 String* string_; |
| 13295 Smi* flags_; | 13308 Smi* flags_; |
| 13296 }; | 13309 }; |
| 13297 | 13310 |
| 13311 |
| 13298 // Utf8StringKey carries a vector of chars as key. | 13312 // Utf8StringKey carries a vector of chars as key. |
| 13299 class Utf8StringKey : public HashTableKey { | 13313 class Utf8StringKey : public HashTableKey { |
| 13300 public: | 13314 public: |
| 13301 explicit Utf8StringKey(Vector<const char> string, uint32_t seed) | 13315 explicit Utf8StringKey(Vector<const char> string, uint32_t seed) |
| 13302 : string_(string), hash_field_(0), seed_(seed) { } | 13316 : string_(string), hash_field_(0), seed_(seed) { } |
| 13303 | 13317 |
| 13304 bool IsMatch(Object* string) { | 13318 bool IsMatch(Object* string) { |
| 13305 return String::cast(string)->IsUtf8EqualTo(string_); | 13319 return String::cast(string)->IsUtf8EqualTo(string_); |
| 13306 } | 13320 } |
| 13307 | 13321 |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13654 uint32_t count = 1; | 13668 uint32_t count = 1; |
| 13655 // EnsureCapacity will guarantee the hash table is never full. | 13669 // EnsureCapacity will guarantee the hash table is never full. |
| 13656 while (true) { | 13670 while (true) { |
| 13657 Object* element = KeyAt(entry); | 13671 Object* element = KeyAt(entry); |
| 13658 if (element->IsUndefined() || element->IsTheHole()) break; | 13672 if (element->IsUndefined() || element->IsTheHole()) break; |
| 13659 entry = NextProbe(entry, count++, capacity); | 13673 entry = NextProbe(entry, count++, capacity); |
| 13660 } | 13674 } |
| 13661 return entry; | 13675 return entry; |
| 13662 } | 13676 } |
| 13663 | 13677 |
| 13678 |
| 13664 // Force instantiation of template instances class. | 13679 // Force instantiation of template instances class. |
| 13665 // Please note this list is compiler dependent. | 13680 // Please note this list is compiler dependent. |
| 13666 | 13681 |
| 13667 template class HashTable<StringTableShape, HashTableKey*>; | 13682 template class HashTable<StringTableShape, HashTableKey*>; |
| 13668 | 13683 |
| 13669 template class HashTable<CompilationCacheShape, HashTableKey*>; | 13684 template class HashTable<CompilationCacheShape, HashTableKey*>; |
| 13670 | 13685 |
| 13671 template class HashTable<MapCacheShape, HashTableKey*>; | 13686 template class HashTable<MapCacheShape, HashTableKey*>; |
| 13672 | 13687 |
| 13673 template class HashTable<ObjectHashTableShape<1>, Object*>; | 13688 template class HashTable<ObjectHashTableShape<1>, Object*>; |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14016 } | 14031 } |
| 14017 | 14032 |
| 14018 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 14033 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 14019 return Smi::FromInt(static_cast<int>(result)); | 14034 return Smi::FromInt(static_cast<int>(result)); |
| 14020 } | 14035 } |
| 14021 ASSERT_NE(NULL, result_double); | 14036 ASSERT_NE(NULL, result_double); |
| 14022 result_double->set_value(static_cast<double>(result)); | 14037 result_double->set_value(static_cast<double>(result)); |
| 14023 return result_double; | 14038 return result_double; |
| 14024 } | 14039 } |
| 14025 | 14040 |
| 14041 |
| 14026 ExternalArrayType JSTypedArray::type() { | 14042 ExternalArrayType JSTypedArray::type() { |
| 14027 switch (elements()->map()->instance_type()) { | 14043 switch (elements()->map()->instance_type()) { |
| 14028 case EXTERNAL_BYTE_ARRAY_TYPE: | 14044 case EXTERNAL_BYTE_ARRAY_TYPE: |
| 14029 return kExternalByteArray; | 14045 return kExternalByteArray; |
| 14030 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: | 14046 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: |
| 14031 return kExternalUnsignedByteArray; | 14047 return kExternalUnsignedByteArray; |
| 14032 case EXTERNAL_SHORT_ARRAY_TYPE: | 14048 case EXTERNAL_SHORT_ARRAY_TYPE: |
| 14033 return kExternalShortArray; | 14049 return kExternalShortArray; |
| 14034 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: | 14050 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: |
| 14035 return kExternalUnsignedShortArray; | 14051 return kExternalUnsignedShortArray; |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14230 } | 14246 } |
| 14231 | 14247 |
| 14232 | 14248 |
| 14233 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 14249 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 14234 ASSERT(!HasFastProperties()); | 14250 ASSERT(!HasFastProperties()); |
| 14235 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 14251 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 14236 return PropertyCell::cast(value); | 14252 return PropertyCell::cast(value); |
| 14237 } | 14253 } |
| 14238 | 14254 |
| 14239 | 14255 |
| 14256 // TODO(mstarzinger): Temporary wrapper until handlified. |
| 14257 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict, |
| 14258 Handle<Name> name, |
| 14259 Handle<Object> value, |
| 14260 PropertyDetails details) { |
| 14261 CALL_HEAP_FUNCTION(dict->GetIsolate(), |
| 14262 dict->Add(*name, *value, details), |
| 14263 NameDictionary); |
| 14264 } |
| 14265 |
| 14266 |
| 14240 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( | 14267 Handle<PropertyCell> GlobalObject::EnsurePropertyCell( |
| 14241 Handle<GlobalObject> global, | 14268 Handle<GlobalObject> global, |
| 14242 Handle<Name> name) { | 14269 Handle<Name> name) { |
| 14243 Isolate* isolate = global->GetIsolate(); | 14270 ASSERT(!global->HasFastProperties()); |
| 14244 CALL_HEAP_FUNCTION(isolate, | 14271 int entry = global->property_dictionary()->FindEntry(*name); |
| 14245 global->EnsurePropertyCell(*name), | |
| 14246 PropertyCell); | |
| 14247 } | |
| 14248 | |
| 14249 | |
| 14250 MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) { | |
| 14251 ASSERT(!HasFastProperties()); | |
| 14252 int entry = property_dictionary()->FindEntry(name); | |
| 14253 if (entry == NameDictionary::kNotFound) { | 14272 if (entry == NameDictionary::kNotFound) { |
| 14254 Heap* heap = GetHeap(); | 14273 Isolate* isolate = global->GetIsolate(); |
| 14255 Object* cell; | 14274 Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell( |
| 14256 { MaybeObject* maybe_cell = | 14275 isolate->factory()->the_hole_value()); |
| 14257 heap->AllocatePropertyCell(heap->the_hole_value()); | |
| 14258 if (!maybe_cell->ToObject(&cell)) return maybe_cell; | |
| 14259 } | |
| 14260 PropertyDetails details(NONE, NORMAL, 0); | 14276 PropertyDetails details(NONE, NORMAL, 0); |
| 14261 details = details.AsDeleted(); | 14277 details = details.AsDeleted(); |
| 14262 Object* dictionary; | 14278 Handle<NameDictionary> dictionary = NameDictionaryAdd( |
| 14263 { MaybeObject* maybe_dictionary = | 14279 handle(global->property_dictionary()), name, cell, details); |
| 14264 property_dictionary()->Add(name, cell, details); | 14280 global->set_properties(*dictionary); |
| 14265 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; | |
| 14266 } | |
| 14267 set_properties(NameDictionary::cast(dictionary)); | |
| 14268 return cell; | 14281 return cell; |
| 14269 } else { | 14282 } else { |
| 14270 Object* value = property_dictionary()->ValueAt(entry); | 14283 Object* value = global->property_dictionary()->ValueAt(entry); |
| 14271 ASSERT(value->IsPropertyCell()); | 14284 ASSERT(value->IsPropertyCell()); |
| 14272 return value; | 14285 return handle(PropertyCell::cast(value)); |
| 14273 } | 14286 } |
| 14274 } | 14287 } |
| 14275 | 14288 |
| 14276 | 14289 |
| 14277 MaybeObject* StringTable::LookupString(String* string, Object** s) { | 14290 MaybeObject* StringTable::LookupString(String* string, Object** s) { |
| 14278 InternalizedStringKey key(string); | 14291 InternalizedStringKey key(string); |
| 14279 return LookupKey(&key, s); | 14292 return LookupKey(&key, s); |
| 14280 } | 14293 } |
| 14281 | 14294 |
| 14282 | 14295 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14395 return LookupKey(&key, s); | 14408 return LookupKey(&key, s); |
| 14396 } | 14409 } |
| 14397 | 14410 |
| 14398 | 14411 |
| 14399 MaybeObject* StringTable::LookupTwoByteString(Vector<const uc16> str, | 14412 MaybeObject* StringTable::LookupTwoByteString(Vector<const uc16> str, |
| 14400 Object** s) { | 14413 Object** s) { |
| 14401 TwoByteStringKey key(str, GetHeap()->HashSeed()); | 14414 TwoByteStringKey key(str, GetHeap()->HashSeed()); |
| 14402 return LookupKey(&key, s); | 14415 return LookupKey(&key, s); |
| 14403 } | 14416 } |
| 14404 | 14417 |
| 14418 |
| 14405 MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) { | 14419 MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) { |
| 14406 int entry = FindEntry(key); | 14420 int entry = FindEntry(key); |
| 14407 | 14421 |
| 14408 // String already in table. | 14422 // String already in table. |
| 14409 if (entry != kNotFound) { | 14423 if (entry != kNotFound) { |
| 14410 *s = KeyAt(entry); | 14424 *s = KeyAt(entry); |
| 14411 return this; | 14425 return this; |
| 14412 } | 14426 } |
| 14413 | 14427 |
| 14414 // Adding new string. Grow table if needed. | 14428 // Adding new string. Grow table if needed. |
| (...skipping 1376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15791 set_elements(GetHeap()->EmptyExternalArrayForMap(map())); | 15805 set_elements(GetHeap()->EmptyExternalArrayForMap(map())); |
| 15792 } | 15806 } |
| 15793 | 15807 |
| 15794 | 15808 |
| 15795 Type* PropertyCell::type() { | 15809 Type* PropertyCell::type() { |
| 15796 return static_cast<Type*>(type_raw()); | 15810 return static_cast<Type*>(type_raw()); |
| 15797 } | 15811 } |
| 15798 | 15812 |
| 15799 | 15813 |
| 15800 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { | 15814 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) { |
| 15815 ASSERT(IsPropertyCell()); |
| 15801 set_type_raw(type, ignored); | 15816 set_type_raw(type, ignored); |
| 15802 } | 15817 } |
| 15803 | 15818 |
| 15804 | 15819 |
| 15820 Type* PropertyCell::UpdateType(Handle<PropertyCell> cell, |
| 15821 Handle<Object> value) { |
| 15822 Isolate* isolate = cell->GetIsolate(); |
| 15823 Handle<Type> old_type(cell->type(), isolate); |
| 15824 Handle<Type> new_type((value->IsSmi() || value->IsJSFunction() || |
| 15825 value->IsUndefined()) |
| 15826 ? Type::Constant(value, isolate) |
| 15827 : Type::Any(), isolate); |
| 15828 |
| 15829 if (new_type->Is(old_type)) { |
| 15830 return *old_type; |
| 15831 } |
| 15832 |
| 15833 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 15834 isolate, DependentCode::kPropertyCellChangedGroup); |
| 15835 |
| 15836 if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) { |
| 15837 return *new_type; |
| 15838 } |
| 15839 |
| 15840 return Type::Any(); |
| 15841 } |
| 15842 |
| 15843 |
| 15844 MaybeObject* PropertyCell::SetValueInferType(Object* value, |
| 15845 WriteBarrierMode ignored) { |
| 15846 set_value(value, ignored); |
| 15847 if (!Type::Any()->Is(type())) { |
| 15848 IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate()); |
| 15849 MaybeObject* maybe_type = trampoline.CallWithReturnValue( |
| 15850 &PropertyCell::UpdateType, |
| 15851 Handle<PropertyCell>(this), |
| 15852 Handle<Object>(value, GetIsolate())); |
| 15853 if (maybe_type->IsFailure()) return maybe_type; |
| 15854 Type* new_type = static_cast<Type*>(maybe_type); |
| 15855 set_type(new_type); |
| 15856 } |
| 15857 return value; |
| 15858 } |
| 15859 |
| 15860 |
| 15805 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) { | 15861 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) { |
| 15806 Handle<DependentCode> dep(dependent_code()); | 15862 Handle<DependentCode> dep(dependent_code()); |
| 15807 Handle<DependentCode> codes = | 15863 Handle<DependentCode> codes = |
| 15808 DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, | 15864 DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup, |
| 15809 info->object_wrapper()); | 15865 info->object_wrapper()); |
| 15810 if (*codes != dependent_code()) set_dependent_code(*codes); | 15866 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 15811 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 15867 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| 15812 Handle<HeapObject>(this), info->zone()); | 15868 Handle<HeapObject>(this), info->zone()); |
| 15813 } | 15869 } |
| 15814 | 15870 |
| 15815 | 15871 |
| 15816 void PropertyCell::AddDependentCode(Handle<Code> code) { | 15872 void PropertyCell::AddDependentCode(Handle<Code> code) { |
| 15817 Handle<DependentCode> codes = DependentCode::Insert( | 15873 Handle<DependentCode> codes = DependentCode::Insert( |
| 15818 Handle<DependentCode>(dependent_code()), | 15874 Handle<DependentCode>(dependent_code()), |
| 15819 DependentCode::kPropertyCellChangedGroup, code); | 15875 DependentCode::kPropertyCellChangedGroup, code); |
| 15820 if (*codes != dependent_code()) set_dependent_code(*codes); | 15876 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 15821 } | 15877 } |
| 15822 | 15878 |
| 15823 | 15879 |
| 15824 } } // namespace v8::internal | 15880 } } // namespace v8::internal |
| OLD | NEW |