| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 accumulator->Add("<ExternalUnsignedIntArray[%u]>", | 973 accumulator->Add("<ExternalUnsignedIntArray[%u]>", |
| 974 ExternalUnsignedIntArray::cast(this)->length()); | 974 ExternalUnsignedIntArray::cast(this)->length()); |
| 975 break; | 975 break; |
| 976 case EXTERNAL_FLOAT_ARRAY_TYPE: | 976 case EXTERNAL_FLOAT_ARRAY_TYPE: |
| 977 accumulator->Add("<ExternalFloatArray[%u]>", | 977 accumulator->Add("<ExternalFloatArray[%u]>", |
| 978 ExternalFloatArray::cast(this)->length()); | 978 ExternalFloatArray::cast(this)->length()); |
| 979 break; | 979 break; |
| 980 case SHARED_FUNCTION_INFO_TYPE: | 980 case SHARED_FUNCTION_INFO_TYPE: |
| 981 accumulator->Add("<SharedFunctionInfo>"); | 981 accumulator->Add("<SharedFunctionInfo>"); |
| 982 break; | 982 break; |
| 983 case JS_MESSAGE_OBJECT_TYPE: |
| 984 accumulator->Add("<JSMessageObject>"); |
| 985 break; |
| 983 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 986 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
| 984 case NAME##_TYPE: \ | 987 case NAME##_TYPE: \ |
| 985 accumulator->Put('<'); \ | 988 accumulator->Put('<'); \ |
| 986 accumulator->Add(#Name); \ | 989 accumulator->Add(#Name); \ |
| 987 accumulator->Put('>'); \ | 990 accumulator->Put('>'); \ |
| 988 break; | 991 break; |
| 989 STRUCT_LIST(MAKE_STRUCT_CASE) | 992 STRUCT_LIST(MAKE_STRUCT_CASE) |
| 990 #undef MAKE_STRUCT_CASE | 993 #undef MAKE_STRUCT_CASE |
| 991 case CODE_TYPE: | 994 case CODE_TYPE: |
| 992 accumulator->Add("<Code>"); | 995 accumulator->Add("<Code>"); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); | 1066 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
| 1064 break; | 1067 break; |
| 1065 case JS_OBJECT_TYPE: | 1068 case JS_OBJECT_TYPE: |
| 1066 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 1069 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 1067 case JS_VALUE_TYPE: | 1070 case JS_VALUE_TYPE: |
| 1068 case JS_ARRAY_TYPE: | 1071 case JS_ARRAY_TYPE: |
| 1069 case JS_REGEXP_TYPE: | 1072 case JS_REGEXP_TYPE: |
| 1070 case JS_GLOBAL_PROXY_TYPE: | 1073 case JS_GLOBAL_PROXY_TYPE: |
| 1071 case JS_GLOBAL_OBJECT_TYPE: | 1074 case JS_GLOBAL_OBJECT_TYPE: |
| 1072 case JS_BUILTINS_OBJECT_TYPE: | 1075 case JS_BUILTINS_OBJECT_TYPE: |
| 1076 case JS_MESSAGE_OBJECT_TYPE: |
| 1073 JSObject::BodyDescriptor::IterateBody(this, object_size, v); | 1077 JSObject::BodyDescriptor::IterateBody(this, object_size, v); |
| 1074 break; | 1078 break; |
| 1075 case JS_FUNCTION_TYPE: | 1079 case JS_FUNCTION_TYPE: |
| 1076 reinterpret_cast<JSFunction*>(this) | 1080 reinterpret_cast<JSFunction*>(this) |
| 1077 ->JSFunctionIterateBody(object_size, v); | 1081 ->JSFunctionIterateBody(object_size, v); |
| 1078 break; | 1082 break; |
| 1079 case ODDBALL_TYPE: | 1083 case ODDBALL_TYPE: |
| 1080 Oddball::BodyDescriptor::IterateBody(this, v); | 1084 Oddball::BodyDescriptor::IterateBody(this, v); |
| 1081 break; | 1085 break; |
| 1082 case PROXY_TYPE: | 1086 case PROXY_TYPE: |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 set_properties(FixedArray::cast(values)); | 1207 set_properties(FixedArray::cast(values)); |
| 1204 } | 1208 } |
| 1205 set_map(new_map); | 1209 set_map(new_map); |
| 1206 return FastPropertyAtPut(index, value); | 1210 return FastPropertyAtPut(index, value); |
| 1207 } | 1211 } |
| 1208 | 1212 |
| 1209 | 1213 |
| 1210 MaybeObject* JSObject::AddFastProperty(String* name, | 1214 MaybeObject* JSObject::AddFastProperty(String* name, |
| 1211 Object* value, | 1215 Object* value, |
| 1212 PropertyAttributes attributes) { | 1216 PropertyAttributes attributes) { |
| 1217 ASSERT(!IsJSGlobalProxy()); |
| 1218 |
| 1213 // Normalize the object if the name is an actual string (not the | 1219 // Normalize the object if the name is an actual string (not the |
| 1214 // hidden symbols) and is not a real identifier. | 1220 // hidden symbols) and is not a real identifier. |
| 1215 StringInputBuffer buffer(name); | 1221 StringInputBuffer buffer(name); |
| 1216 if (!ScannerConstants::IsIdentifier(&buffer) | 1222 if (!ScannerConstants::IsIdentifier(&buffer) |
| 1217 && name != Heap::hidden_symbol()) { | 1223 && name != Heap::hidden_symbol()) { |
| 1218 Object* obj; | 1224 Object* obj; |
| 1219 { MaybeObject* maybe_obj = | 1225 { MaybeObject* maybe_obj = |
| 1220 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1226 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1221 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1227 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1222 } | 1228 } |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 } | 1393 } |
| 1388 | 1394 |
| 1389 | 1395 |
| 1390 MaybeObject* JSObject::AddProperty(String* name, | 1396 MaybeObject* JSObject::AddProperty(String* name, |
| 1391 Object* value, | 1397 Object* value, |
| 1392 PropertyAttributes attributes) { | 1398 PropertyAttributes attributes) { |
| 1393 ASSERT(!IsJSGlobalProxy()); | 1399 ASSERT(!IsJSGlobalProxy()); |
| 1394 if (!map()->is_extensible()) { | 1400 if (!map()->is_extensible()) { |
| 1395 Handle<Object> args[1] = {Handle<String>(name)}; | 1401 Handle<Object> args[1] = {Handle<String>(name)}; |
| 1396 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 1402 return Top::Throw(*Factory::NewTypeError("object_not_extensible", |
| 1397 HandleVector(args, 1))); | 1403 HandleVector(args, 1))); |
| 1398 } | 1404 } |
| 1399 if (HasFastProperties()) { | 1405 if (HasFastProperties()) { |
| 1400 // Ensure the descriptor array does not get too big. | 1406 // Ensure the descriptor array does not get too big. |
| 1401 if (map()->instance_descriptors()->number_of_descriptors() < | 1407 if (map()->instance_descriptors()->number_of_descriptors() < |
| 1402 DescriptorArray::kMaxNumberOfDescriptors) { | 1408 DescriptorArray::kMaxNumberOfDescriptors) { |
| 1403 if (value->IsJSFunction() && !Heap::InNewSpace(value)) { | 1409 if (value->IsJSFunction() && !Heap::InNewSpace(value)) { |
| 1404 return AddConstantFunctionProperty(name, | 1410 return AddConstantFunctionProperty(name, |
| 1405 JSFunction::cast(value), | 1411 JSFunction::cast(value), |
| 1406 attributes); | 1412 attributes); |
| 1407 } else { | 1413 } else { |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1695 } | 1701 } |
| 1696 if (result->type() == CALLBACKS) { | 1702 if (result->type() == CALLBACKS) { |
| 1697 return; | 1703 return; |
| 1698 } | 1704 } |
| 1699 } | 1705 } |
| 1700 } | 1706 } |
| 1701 result->NotFound(); | 1707 result->NotFound(); |
| 1702 } | 1708 } |
| 1703 | 1709 |
| 1704 | 1710 |
| 1705 bool JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, | 1711 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, |
| 1706 Object* value) { | 1712 Object* value, |
| 1713 bool* found) { |
| 1707 for (Object* pt = GetPrototype(); | 1714 for (Object* pt = GetPrototype(); |
| 1708 pt != Heap::null_value(); | 1715 pt != Heap::null_value(); |
| 1709 pt = pt->GetPrototype()) { | 1716 pt = pt->GetPrototype()) { |
| 1710 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 1717 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 1711 continue; | 1718 continue; |
| 1712 } | 1719 } |
| 1713 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); | 1720 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| 1714 int entry = dictionary->FindEntry(index); | 1721 int entry = dictionary->FindEntry(index); |
| 1715 if (entry != NumberDictionary::kNotFound) { | 1722 if (entry != NumberDictionary::kNotFound) { |
| 1716 Object* element = dictionary->ValueAt(entry); | |
| 1717 PropertyDetails details = dictionary->DetailsAt(entry); | 1723 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1718 if (details.type() == CALLBACKS) { | 1724 if (details.type() == CALLBACKS) { |
| 1719 SetElementWithCallback(element, index, value, JSObject::cast(pt)); | 1725 *found = true; |
| 1720 return true; | 1726 return SetElementWithCallback( |
| 1727 dictionary->ValueAt(entry), index, value, JSObject::cast(pt)); |
| 1721 } | 1728 } |
| 1722 } | 1729 } |
| 1723 } | 1730 } |
| 1724 return false; | 1731 *found = false; |
| 1732 return Heap::the_hole_value(); |
| 1725 } | 1733 } |
| 1726 | 1734 |
| 1727 | 1735 |
| 1728 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { | 1736 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { |
| 1729 DescriptorArray* descriptors = map()->instance_descriptors(); | 1737 DescriptorArray* descriptors = map()->instance_descriptors(); |
| 1730 int number = descriptors->SearchWithCache(name); | 1738 int number = descriptors->SearchWithCache(name); |
| 1731 if (number != DescriptorArray::kNotFound) { | 1739 if (number != DescriptorArray::kNotFound) { |
| 1732 result->DescriptorResult(this, descriptors->GetDetails(number), number); | 1740 result->DescriptorResult(this, descriptors->GetDetails(number), number); |
| 1733 } else { | 1741 } else { |
| 1734 result->NotFound(); | 1742 result->NotFound(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1817 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1825 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1818 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; | 1826 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; |
| 1819 } | 1827 } |
| 1820 result->NotFound(); | 1828 result->NotFound(); |
| 1821 } | 1829 } |
| 1822 | 1830 |
| 1823 | 1831 |
| 1824 // We only need to deal with CALLBACKS and INTERCEPTORS | 1832 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 1825 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, | 1833 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, |
| 1826 String* name, | 1834 String* name, |
| 1827 Object* value) { | 1835 Object* value, |
| 1828 if (!result->IsProperty()) { | 1836 bool check_prototype) { |
| 1837 if (check_prototype && !result->IsProperty()) { |
| 1829 LookupCallbackSetterInPrototypes(name, result); | 1838 LookupCallbackSetterInPrototypes(name, result); |
| 1830 } | 1839 } |
| 1831 | 1840 |
| 1832 if (result->IsProperty()) { | 1841 if (result->IsProperty()) { |
| 1833 if (!result->IsReadOnly()) { | 1842 if (!result->IsReadOnly()) { |
| 1834 switch (result->type()) { | 1843 switch (result->type()) { |
| 1835 case CALLBACKS: { | 1844 case CALLBACKS: { |
| 1836 Object* obj = result->GetCallbackObject(); | 1845 Object* obj = result->GetCallbackObject(); |
| 1837 if (obj->IsAccessorInfo()) { | 1846 if (obj->IsAccessorInfo()) { |
| 1838 AccessorInfo* info = AccessorInfo::cast(obj); | 1847 AccessorInfo* info = AccessorInfo::cast(obj); |
| 1839 if (info->all_can_write()) { | 1848 if (info->all_can_write()) { |
| 1840 return SetPropertyWithCallback(result->GetCallbackObject(), | 1849 return SetPropertyWithCallback(result->GetCallbackObject(), |
| 1841 name, | 1850 name, |
| 1842 value, | 1851 value, |
| 1843 result->holder()); | 1852 result->holder()); |
| 1844 } | 1853 } |
| 1845 } | 1854 } |
| 1846 break; | 1855 break; |
| 1847 } | 1856 } |
| 1848 case INTERCEPTOR: { | 1857 case INTERCEPTOR: { |
| 1849 // Try lookup real named properties. Note that only property can be | 1858 // Try lookup real named properties. Note that only property can be |
| 1850 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | 1859 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. |
| 1851 LookupResult r; | 1860 LookupResult r; |
| 1852 LookupRealNamedProperty(name, &r); | 1861 LookupRealNamedProperty(name, &r); |
| 1853 if (r.IsProperty()) { | 1862 if (r.IsProperty()) { |
| 1854 return SetPropertyWithFailedAccessCheck(&r, name, value); | 1863 return SetPropertyWithFailedAccessCheck(&r, name, value, |
| 1864 check_prototype); |
| 1855 } | 1865 } |
| 1856 break; | 1866 break; |
| 1857 } | 1867 } |
| 1858 default: { | 1868 default: { |
| 1859 break; | 1869 break; |
| 1860 } | 1870 } |
| 1861 } | 1871 } |
| 1862 } | 1872 } |
| 1863 } | 1873 } |
| 1864 | 1874 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1885 { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); | 1895 { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); |
| 1886 if (maybe_symbol_version->ToObject(&symbol_version)) { | 1896 if (maybe_symbol_version->ToObject(&symbol_version)) { |
| 1887 name = String::cast(symbol_version); | 1897 name = String::cast(symbol_version); |
| 1888 } | 1898 } |
| 1889 } | 1899 } |
| 1890 } | 1900 } |
| 1891 | 1901 |
| 1892 // Check access rights if needed. | 1902 // Check access rights if needed. |
| 1893 if (IsAccessCheckNeeded() | 1903 if (IsAccessCheckNeeded() |
| 1894 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1904 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1895 return SetPropertyWithFailedAccessCheck(result, name, value); | 1905 return SetPropertyWithFailedAccessCheck(result, name, value, true); |
| 1896 } | 1906 } |
| 1897 | 1907 |
| 1898 if (IsJSGlobalProxy()) { | 1908 if (IsJSGlobalProxy()) { |
| 1899 Object* proto = GetPrototype(); | 1909 Object* proto = GetPrototype(); |
| 1900 if (proto->IsNull()) return value; | 1910 if (proto->IsNull()) return value; |
| 1901 ASSERT(proto->IsJSGlobalObject()); | 1911 ASSERT(proto->IsJSGlobalObject()); |
| 1902 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); | 1912 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); |
| 1903 } | 1913 } |
| 1904 | 1914 |
| 1905 if (!result->IsProperty() && !IsJSContextExtensionObject()) { | 1915 if (!result->IsProperty() && !IsJSContextExtensionObject()) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1975 return value; | 1985 return value; |
| 1976 } | 1986 } |
| 1977 | 1987 |
| 1978 | 1988 |
| 1979 // Set a real local property, even if it is READ_ONLY. If the property is not | 1989 // Set a real local property, even if it is READ_ONLY. If the property is not |
| 1980 // present, add it with attributes NONE. This code is an exact clone of | 1990 // present, add it with attributes NONE. This code is an exact clone of |
| 1981 // SetProperty, with the check for IsReadOnly and the check for a | 1991 // SetProperty, with the check for IsReadOnly and the check for a |
| 1982 // callback setter removed. The two lines looking up the LookupResult | 1992 // callback setter removed. The two lines looking up the LookupResult |
| 1983 // result are also added. If one of the functions is changed, the other | 1993 // result are also added. If one of the functions is changed, the other |
| 1984 // should be. | 1994 // should be. |
| 1985 MaybeObject* JSObject::IgnoreAttributesAndSetLocalProperty( | 1995 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 1986 String* name, | 1996 String* name, |
| 1987 Object* value, | 1997 Object* value, |
| 1988 PropertyAttributes attributes) { | 1998 PropertyAttributes attributes) { |
| 1989 // Make sure that the top context does not change when doing callbacks or | 1999 // Make sure that the top context does not change when doing callbacks or |
| 1990 // interceptor calls. | 2000 // interceptor calls. |
| 1991 AssertNoContextChange ncc; | 2001 AssertNoContextChange ncc; |
| 1992 LookupResult result; | 2002 LookupResult result; |
| 1993 LocalLookup(name, &result); | 2003 LocalLookup(name, &result); |
| 1994 // Check access rights if needed. | 2004 // Check access rights if needed. |
| 1995 if (IsAccessCheckNeeded() | 2005 if (IsAccessCheckNeeded() |
| 1996 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2006 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1997 return SetPropertyWithFailedAccessCheck(&result, name, value); | 2007 return SetPropertyWithFailedAccessCheck(&result, name, value, false); |
| 1998 } | 2008 } |
| 1999 | 2009 |
| 2000 if (IsJSGlobalProxy()) { | 2010 if (IsJSGlobalProxy()) { |
| 2001 Object* proto = GetPrototype(); | 2011 Object* proto = GetPrototype(); |
| 2002 if (proto->IsNull()) return value; | 2012 if (proto->IsNull()) return value; |
| 2003 ASSERT(proto->IsJSGlobalObject()); | 2013 ASSERT(proto->IsJSGlobalObject()); |
| 2004 return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty( | 2014 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( |
| 2005 name, | 2015 name, |
| 2006 value, | 2016 value, |
| 2007 attributes); | 2017 attributes); |
| 2008 } | 2018 } |
| 2009 | 2019 |
| 2010 // Check for accessor in prototype chain removed here in clone. | 2020 // Check for accessor in prototype chain removed here in clone. |
| 2011 if (!result.IsFound()) { | 2021 if (!result.IsFound()) { |
| 2012 // Neither properties nor transitions found. | 2022 // Neither properties nor transitions found. |
| 2013 return AddProperty(name, value, attributes); | 2023 return AddProperty(name, value, attributes); |
| 2014 } | 2024 } |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 } | 2286 } |
| 2277 | 2287 |
| 2278 | 2288 |
| 2279 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, | 2289 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
| 2280 int expected_additional_properties) { | 2290 int expected_additional_properties) { |
| 2281 if (!HasFastProperties()) return this; | 2291 if (!HasFastProperties()) return this; |
| 2282 | 2292 |
| 2283 // The global object is always normalized. | 2293 // The global object is always normalized. |
| 2284 ASSERT(!IsGlobalObject()); | 2294 ASSERT(!IsGlobalObject()); |
| 2285 | 2295 |
| 2296 // JSGlobalProxy must never be normalized |
| 2297 ASSERT(!IsJSGlobalProxy()); |
| 2298 |
| 2286 // Allocate new content. | 2299 // Allocate new content. |
| 2287 int property_count = map()->NumberOfDescribedProperties(); | 2300 int property_count = map()->NumberOfDescribedProperties(); |
| 2288 if (expected_additional_properties > 0) { | 2301 if (expected_additional_properties > 0) { |
| 2289 property_count += expected_additional_properties; | 2302 property_count += expected_additional_properties; |
| 2290 } else { | 2303 } else { |
| 2291 property_count += 2; // Make space for two more properties. | 2304 property_count += 2; // Make space for two more properties. |
| 2292 } | 2305 } |
| 2293 Object* obj; | 2306 Object* obj; |
| 2294 { MaybeObject* maybe_obj = | 2307 { MaybeObject* maybe_obj = |
| 2295 StringDictionary::Allocate(property_count); | 2308 StringDictionary::Allocate(property_count); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2601 case EXTERNAL_INT_ELEMENTS: | 2614 case EXTERNAL_INT_ELEMENTS: |
| 2602 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2615 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2603 case EXTERNAL_FLOAT_ELEMENTS: | 2616 case EXTERNAL_FLOAT_ELEMENTS: |
| 2604 // Pixel and external array elements cannot be deleted. Just | 2617 // Pixel and external array elements cannot be deleted. Just |
| 2605 // silently ignore here. | 2618 // silently ignore here. |
| 2606 break; | 2619 break; |
| 2607 case DICTIONARY_ELEMENTS: { | 2620 case DICTIONARY_ELEMENTS: { |
| 2608 NumberDictionary* dictionary = element_dictionary(); | 2621 NumberDictionary* dictionary = element_dictionary(); |
| 2609 int entry = dictionary->FindEntry(index); | 2622 int entry = dictionary->FindEntry(index); |
| 2610 if (entry != NumberDictionary::kNotFound) { | 2623 if (entry != NumberDictionary::kNotFound) { |
| 2611 return dictionary->DeleteProperty(entry, mode); | 2624 Object* result = dictionary->DeleteProperty(entry, mode); |
| 2625 if (mode == STRICT_DELETION && result == Heap::false_value()) { |
| 2626 // In strict mode, deleting a non-configurable property throws |
| 2627 // exception. dictionary->DeleteProperty will return false_value() |
| 2628 // if a non-configurable property is being deleted. |
| 2629 HandleScope scope; |
| 2630 Handle<Object> i = Factory::NewNumberFromUint(index); |
| 2631 Handle<Object> args[2] = { i, Handle<Object>(this) }; |
| 2632 return Top::Throw(*Factory::NewTypeError("strict_delete_property", |
| 2633 HandleVector(args, 2))); |
| 2634 } |
| 2612 } | 2635 } |
| 2613 break; | 2636 break; |
| 2614 } | 2637 } |
| 2615 default: | 2638 default: |
| 2616 UNREACHABLE(); | 2639 UNREACHABLE(); |
| 2617 break; | 2640 break; |
| 2618 } | 2641 } |
| 2619 return Heap::true_value(); | 2642 return Heap::true_value(); |
| 2620 } | 2643 } |
| 2621 | 2644 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2640 | 2663 |
| 2641 uint32_t index = 0; | 2664 uint32_t index = 0; |
| 2642 if (name->AsArrayIndex(&index)) { | 2665 if (name->AsArrayIndex(&index)) { |
| 2643 return DeleteElement(index, mode); | 2666 return DeleteElement(index, mode); |
| 2644 } else { | 2667 } else { |
| 2645 LookupResult result; | 2668 LookupResult result; |
| 2646 LocalLookup(name, &result); | 2669 LocalLookup(name, &result); |
| 2647 if (!result.IsProperty()) return Heap::true_value(); | 2670 if (!result.IsProperty()) return Heap::true_value(); |
| 2648 // Ignore attributes if forcing a deletion. | 2671 // Ignore attributes if forcing a deletion. |
| 2649 if (result.IsDontDelete() && mode != FORCE_DELETION) { | 2672 if (result.IsDontDelete() && mode != FORCE_DELETION) { |
| 2673 if (mode == STRICT_DELETION) { |
| 2674 // Deleting a non-configurable property in strict mode. |
| 2675 HandleScope scope; |
| 2676 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; |
| 2677 return Top::Throw(*Factory::NewTypeError("strict_delete_property", |
| 2678 HandleVector(args, 2))); |
| 2679 } |
| 2650 return Heap::false_value(); | 2680 return Heap::false_value(); |
| 2651 } | 2681 } |
| 2652 // Check for interceptor. | 2682 // Check for interceptor. |
| 2653 if (result.type() == INTERCEPTOR) { | 2683 if (result.type() == INTERCEPTOR) { |
| 2654 // Skip interceptor if forcing a deletion. | 2684 // Skip interceptor if forcing a deletion. |
| 2655 if (mode == FORCE_DELETION) { | 2685 if (mode == FORCE_DELETION) { |
| 2656 return DeletePropertyPostInterceptor(name, mode); | 2686 return DeletePropertyPostInterceptor(name, mode); |
| 2657 } | 2687 } |
| 2658 return DeletePropertyWithInterceptor(name); | 2688 return DeletePropertyWithInterceptor(name); |
| 2659 } | 2689 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2762 return context->extension()->ReferencesObject(obj); | 2792 return context->extension()->ReferencesObject(obj); |
| 2763 } | 2793 } |
| 2764 } | 2794 } |
| 2765 | 2795 |
| 2766 // No references to object. | 2796 // No references to object. |
| 2767 return false; | 2797 return false; |
| 2768 } | 2798 } |
| 2769 | 2799 |
| 2770 | 2800 |
| 2771 MaybeObject* JSObject::PreventExtensions() { | 2801 MaybeObject* JSObject::PreventExtensions() { |
| 2802 if (IsJSGlobalProxy()) { |
| 2803 Object* proto = GetPrototype(); |
| 2804 if (proto->IsNull()) return this; |
| 2805 ASSERT(proto->IsJSGlobalObject()); |
| 2806 return JSObject::cast(proto)->PreventExtensions(); |
| 2807 } |
| 2808 |
| 2772 // If there are fast elements we normalize. | 2809 // If there are fast elements we normalize. |
| 2773 if (HasFastElements()) { | 2810 if (HasFastElements()) { |
| 2774 Object* ok; | 2811 Object* ok; |
| 2775 { MaybeObject* maybe_ok = NormalizeElements(); | 2812 { MaybeObject* maybe_ok = NormalizeElements(); |
| 2776 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 2813 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 2777 } | 2814 } |
| 2778 } | 2815 } |
| 2779 // Make sure that we never go back to fast case. | 2816 // Make sure that we never go back to fast case. |
| 2780 element_dictionary()->set_requires_slow_elements(); | 2817 element_dictionary()->set_requires_slow_elements(); |
| 2781 | 2818 |
| (...skipping 2609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5391 // Iterate over all fields in the body but take care in dealing with | 5428 // Iterate over all fields in the body but take care in dealing with |
| 5392 // the code entry. | 5429 // the code entry. |
| 5393 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 5430 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 5394 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 5431 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 5395 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 5432 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 5396 } | 5433 } |
| 5397 | 5434 |
| 5398 | 5435 |
| 5399 void JSFunction::MarkForLazyRecompilation() { | 5436 void JSFunction::MarkForLazyRecompilation() { |
| 5400 ASSERT(is_compiled() && !IsOptimized()); | 5437 ASSERT(is_compiled() && !IsOptimized()); |
| 5401 ASSERT(shared()->allows_lazy_compilation()); | 5438 ASSERT(shared()->allows_lazy_compilation() || |
| 5439 code()->optimizable()); |
| 5402 ReplaceCode(Builtins::builtin(Builtins::LazyRecompile)); | 5440 ReplaceCode(Builtins::builtin(Builtins::LazyRecompile)); |
| 5403 } | 5441 } |
| 5404 | 5442 |
| 5405 | 5443 |
| 5406 uint32_t JSFunction::SourceHash() { | 5444 uint32_t JSFunction::SourceHash() { |
| 5407 uint32_t hash = 0; | 5445 uint32_t hash = 0; |
| 5408 Object* script = shared()->script(); | 5446 Object* script = shared()->script(); |
| 5409 if (!script->IsUndefined()) { | 5447 if (!script->IsUndefined()) { |
| 5410 Object* source = Script::cast(script)->source(); | 5448 Object* source = Script::cast(script)->source(); |
| 5411 if (source->IsUndefined()) hash = String::cast(source)->Hash(); | 5449 if (source->IsUndefined()) hash = String::cast(source)->Hash(); |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5907 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 5945 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 5908 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 5946 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
| 5909 RelocInfo::kApplyMask; | 5947 RelocInfo::kApplyMask; |
| 5910 Assembler* origin = desc.origin; // Needed to find target_object on X64. | 5948 Assembler* origin = desc.origin; // Needed to find target_object on X64. |
| 5911 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 5949 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 5912 RelocInfo::Mode mode = it.rinfo()->rmode(); | 5950 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 5913 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 5951 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 5914 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 5952 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 5915 it.rinfo()->set_target_object(*p); | 5953 it.rinfo()->set_target_object(*p); |
| 5916 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { | 5954 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { |
| 5917 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); | 5955 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); |
| 5918 it.rinfo()->set_target_cell(*cell); | 5956 it.rinfo()->set_target_cell(*cell); |
| 5919 } else if (RelocInfo::IsCodeTarget(mode)) { | 5957 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 5920 // rewrite code handles in inline cache targets to direct | 5958 // rewrite code handles in inline cache targets to direct |
| 5921 // pointers to the first instruction in the code object | 5959 // pointers to the first instruction in the code object |
| 5922 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 5960 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 5923 Code* code = Code::cast(*p); | 5961 Code* code = Code::cast(*p); |
| 5924 it.rinfo()->set_target_address(code->instruction_start()); | 5962 it.rinfo()->set_target_address(code->instruction_start()); |
| 5925 } else { | 5963 } else { |
| 5926 it.rinfo()->apply(delta); | 5964 it.rinfo()->apply(delta); |
| 5927 } | 5965 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5979 if (statement_position < p && p <= position) { | 6017 if (statement_position < p && p <= position) { |
| 5980 statement_position = p; | 6018 statement_position = p; |
| 5981 } | 6019 } |
| 5982 } | 6020 } |
| 5983 it.next(); | 6021 it.next(); |
| 5984 } | 6022 } |
| 5985 return statement_position; | 6023 return statement_position; |
| 5986 } | 6024 } |
| 5987 | 6025 |
| 5988 | 6026 |
| 5989 uint8_t* Code::GetSafepointEntry(Address pc) { | 6027 SafepointEntry Code::GetSafepointEntry(Address pc) { |
| 5990 SafepointTable table(this); | 6028 SafepointTable table(this); |
| 5991 unsigned pc_offset = static_cast<unsigned>(pc - instruction_start()); | 6029 return table.FindEntry(pc); |
| 5992 for (unsigned i = 0; i < table.length(); i++) { | |
| 5993 // TODO(kasperl): Replace the linear search with binary search. | |
| 5994 if (table.GetPcOffset(i) == pc_offset) return table.GetEntry(i); | |
| 5995 } | |
| 5996 return NULL; | |
| 5997 } | 6030 } |
| 5998 | 6031 |
| 5999 | 6032 |
| 6000 void Code::SetNoStackCheckTable() { | 6033 void Code::SetNoStackCheckTable() { |
| 6001 // Indicate the absence of a stack-check table by a table start after the | 6034 // Indicate the absence of a stack-check table by a table start after the |
| 6002 // end of the instructions. Table start must be aligned, so round up. | 6035 // end of the instructions. Table start must be aligned, so round up. |
| 6003 set_stack_check_table_start(RoundUp(instruction_size(), kIntSize)); | 6036 set_stack_check_table_offset(RoundUp(instruction_size(), kIntSize)); |
| 6004 } | 6037 } |
| 6005 | 6038 |
| 6006 | 6039 |
| 6007 Map* Code::FindFirstMap() { | 6040 Map* Code::FindFirstMap() { |
| 6008 ASSERT(is_inline_cache_stub()); | 6041 ASSERT(is_inline_cache_stub()); |
| 6009 AssertNoAllocation no_allocation; | 6042 AssertNoAllocation no_allocation; |
| 6010 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 6043 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 6011 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 6044 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 6012 RelocInfo* info = it.rinfo(); | 6045 RelocInfo* info = it.rinfo(); |
| 6013 Object* object = info->target_object(); | 6046 Object* object = info->target_object(); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6216 case INTERCEPTOR: return "INTERCEPTOR"; | 6249 case INTERCEPTOR: return "INTERCEPTOR"; |
| 6217 case MAP_TRANSITION: return "MAP_TRANSITION"; | 6250 case MAP_TRANSITION: return "MAP_TRANSITION"; |
| 6218 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; | 6251 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; |
| 6219 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; | 6252 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; |
| 6220 } | 6253 } |
| 6221 UNREACHABLE(); | 6254 UNREACHABLE(); |
| 6222 return NULL; | 6255 return NULL; |
| 6223 } | 6256 } |
| 6224 | 6257 |
| 6225 | 6258 |
| 6259 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
| 6260 const char* name = NULL; |
| 6261 switch (kind) { |
| 6262 case CALL_IC: |
| 6263 if (extra == STRING_INDEX_OUT_OF_BOUNDS) { |
| 6264 name = "STRING_INDEX_OUT_OF_BOUNDS"; |
| 6265 } |
| 6266 break; |
| 6267 case STORE_IC: |
| 6268 if (extra == StoreIC::kStoreICStrict) { |
| 6269 name = "STRICT"; |
| 6270 } |
| 6271 break; |
| 6272 default: |
| 6273 break; |
| 6274 } |
| 6275 if (name != NULL) { |
| 6276 PrintF(out, "extra_ic_state = %s\n", name); |
| 6277 } else { |
| 6278 PrintF(out, "etra_ic_state = %d\n", extra); |
| 6279 } |
| 6280 } |
| 6281 |
| 6282 |
| 6226 void Code::Disassemble(const char* name, FILE* out) { | 6283 void Code::Disassemble(const char* name, FILE* out) { |
| 6227 PrintF(out, "kind = %s\n", Kind2String(kind())); | 6284 PrintF(out, "kind = %s\n", Kind2String(kind())); |
| 6228 if (is_inline_cache_stub()) { | 6285 if (is_inline_cache_stub()) { |
| 6229 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); | 6286 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); |
| 6287 PrintExtraICState(out, kind(), extra_ic_state()); |
| 6230 PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); | 6288 PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); |
| 6231 if (ic_state() == MONOMORPHIC) { | 6289 if (ic_state() == MONOMORPHIC) { |
| 6232 PrintF(out, "type = %s\n", PropertyType2String(type())); | 6290 PrintF(out, "type = %s\n", PropertyType2String(type())); |
| 6233 } | 6291 } |
| 6234 } | 6292 } |
| 6235 if ((name != NULL) && (name[0] != '\0')) { | 6293 if ((name != NULL) && (name[0] != '\0')) { |
| 6236 PrintF(out, "name = %s\n", name); | 6294 PrintF(out, "name = %s\n", name); |
| 6237 } | 6295 } |
| 6238 if (kind() == OPTIMIZED_FUNCTION) { | 6296 if (kind() == OPTIMIZED_FUNCTION) { |
| 6239 PrintF(out, "stack_slots = %d\n", stack_slots()); | 6297 PrintF(out, "stack_slots = %d\n", stack_slots()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 6257 #endif | 6315 #endif |
| 6258 | 6316 |
| 6259 if (kind() == OPTIMIZED_FUNCTION) { | 6317 if (kind() == OPTIMIZED_FUNCTION) { |
| 6260 SafepointTable table(this); | 6318 SafepointTable table(this); |
| 6261 PrintF(out, "Safepoints (size = %u)\n", table.size()); | 6319 PrintF(out, "Safepoints (size = %u)\n", table.size()); |
| 6262 for (unsigned i = 0; i < table.length(); i++) { | 6320 for (unsigned i = 0; i < table.length(); i++) { |
| 6263 unsigned pc_offset = table.GetPcOffset(i); | 6321 unsigned pc_offset = table.GetPcOffset(i); |
| 6264 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); | 6322 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); |
| 6265 table.PrintEntry(i); | 6323 table.PrintEntry(i); |
| 6266 PrintF(out, " (sp -> fp)"); | 6324 PrintF(out, " (sp -> fp)"); |
| 6267 int deoptimization_index = table.GetDeoptimizationIndex(i); | 6325 SafepointEntry entry = table.GetEntry(i); |
| 6268 if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { | 6326 if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) { |
| 6269 PrintF(out, " %6d", deoptimization_index); | 6327 PrintF(out, " %6d", entry.deoptimization_index()); |
| 6270 } else { | 6328 } else { |
| 6271 PrintF(out, " <none>"); | 6329 PrintF(out, " <none>"); |
| 6272 } | 6330 } |
| 6331 if (entry.argument_count() > 0) { |
| 6332 PrintF(out, " argc: %d", entry.argument_count()); |
| 6333 } |
| 6273 PrintF(out, "\n"); | 6334 PrintF(out, "\n"); |
| 6274 } | 6335 } |
| 6275 PrintF(out, "\n"); | 6336 PrintF(out, "\n"); |
| 6276 } else if (kind() == FUNCTION) { | 6337 } else if (kind() == FUNCTION) { |
| 6277 unsigned offset = stack_check_table_start(); | 6338 unsigned offset = stack_check_table_offset(); |
| 6278 // If there is no stack check table, the "table start" will at or after | 6339 // If there is no stack check table, the "table start" will at or after |
| 6279 // (due to alignment) the end of the instruction stream. | 6340 // (due to alignment) the end of the instruction stream. |
| 6280 if (static_cast<int>(offset) < instruction_size()) { | 6341 if (static_cast<int>(offset) < instruction_size()) { |
| 6281 unsigned* address = | 6342 unsigned* address = |
| 6282 reinterpret_cast<unsigned*>(instruction_start() + offset); | 6343 reinterpret_cast<unsigned*>(instruction_start() + offset); |
| 6283 unsigned length = address[0]; | 6344 unsigned length = address[0]; |
| 6284 PrintF(out, "Stack checks (size = %u)\n", length); | 6345 PrintF(out, "Stack checks (size = %u)\n", length); |
| 6285 PrintF(out, "ast_id pc_offset\n"); | 6346 PrintF(out, "ast_id pc_offset\n"); |
| 6286 for (unsigned i = 0; i < length; ++i) { | 6347 for (unsigned i = 0; i < length; ++i) { |
| 6287 unsigned index = (2 * i) + 1; | 6348 unsigned index = (2 * i) + 1; |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6668 | 6729 |
| 6669 | 6730 |
| 6670 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { | 6731 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { |
| 6671 // Check access rights if needed. | 6732 // Check access rights if needed. |
| 6672 if (IsAccessCheckNeeded() && | 6733 if (IsAccessCheckNeeded() && |
| 6673 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6734 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6674 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6735 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6675 return UNDEFINED_ELEMENT; | 6736 return UNDEFINED_ELEMENT; |
| 6676 } | 6737 } |
| 6677 | 6738 |
| 6739 if (IsJSGlobalProxy()) { |
| 6740 Object* proto = GetPrototype(); |
| 6741 if (proto->IsNull()) return UNDEFINED_ELEMENT; |
| 6742 ASSERT(proto->IsJSGlobalObject()); |
| 6743 return JSObject::cast(proto)->HasLocalElement(index); |
| 6744 } |
| 6745 |
| 6678 // Check for lookup interceptor | 6746 // Check for lookup interceptor |
| 6679 if (HasIndexedInterceptor()) { | 6747 if (HasIndexedInterceptor()) { |
| 6680 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT | 6748 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT |
| 6681 : UNDEFINED_ELEMENT; | 6749 : UNDEFINED_ELEMENT; |
| 6682 } | 6750 } |
| 6683 | 6751 |
| 6684 // Handle [] on String objects. | 6752 // Handle [] on String objects. |
| 6685 if (this->IsStringObjectWithCharacterAt(index)) { | 6753 if (this->IsStringObjectWithCharacterAt(index)) { |
| 6686 return STRING_CHARACTER_ELEMENT; | 6754 return STRING_CHARACTER_ELEMENT; |
| 6687 } | 6755 } |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6939 ASSERT(HasFastElements()); | 7007 ASSERT(HasFastElements()); |
| 6940 | 7008 |
| 6941 Object* elms_obj; | 7009 Object* elms_obj; |
| 6942 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); | 7010 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); |
| 6943 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; | 7011 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
| 6944 } | 7012 } |
| 6945 FixedArray* elms = FixedArray::cast(elms_obj); | 7013 FixedArray* elms = FixedArray::cast(elms_obj); |
| 6946 uint32_t elms_length = static_cast<uint32_t>(elms->length()); | 7014 uint32_t elms_length = static_cast<uint32_t>(elms->length()); |
| 6947 | 7015 |
| 6948 if (check_prototype && | 7016 if (check_prototype && |
| 6949 (index >= elms_length || elms->get(index)->IsTheHole()) && | 7017 (index >= elms_length || elms->get(index)->IsTheHole())) { |
| 6950 SetElementWithCallbackSetterInPrototypes(index, value)) { | 7018 bool found; |
| 6951 return value; | 7019 MaybeObject* result = |
| 7020 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7021 if (found) return result; |
| 6952 } | 7022 } |
| 6953 | 7023 |
| 6954 | 7024 |
| 6955 // Check whether there is extra space in fixed array.. | 7025 // Check whether there is extra space in fixed array.. |
| 6956 if (index < elms_length) { | 7026 if (index < elms_length) { |
| 6957 elms->set(index, value); | 7027 elms->set(index, value); |
| 6958 if (IsJSArray()) { | 7028 if (IsJSArray()) { |
| 6959 // Update the length of the array if needed. | 7029 // Update the length of the array if needed. |
| 6960 uint32_t array_length = 0; | 7030 uint32_t array_length = 0; |
| 6961 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 7031 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7073 Object* element = dictionary->ValueAt(entry); | 7143 Object* element = dictionary->ValueAt(entry); |
| 7074 PropertyDetails details = dictionary->DetailsAt(entry); | 7144 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7075 if (details.type() == CALLBACKS) { | 7145 if (details.type() == CALLBACKS) { |
| 7076 return SetElementWithCallback(element, index, value, this); | 7146 return SetElementWithCallback(element, index, value, this); |
| 7077 } else { | 7147 } else { |
| 7078 dictionary->UpdateMaxNumberKey(index); | 7148 dictionary->UpdateMaxNumberKey(index); |
| 7079 dictionary->ValueAtPut(entry, value); | 7149 dictionary->ValueAtPut(entry, value); |
| 7080 } | 7150 } |
| 7081 } else { | 7151 } else { |
| 7082 // Index not already used. Look for an accessor in the prototype chain. | 7152 // Index not already used. Look for an accessor in the prototype chain. |
| 7083 if (check_prototype && | 7153 if (check_prototype) { |
| 7084 SetElementWithCallbackSetterInPrototypes(index, value)) { | 7154 bool found; |
| 7085 return value; | 7155 MaybeObject* result = |
| 7156 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7157 if (found) return result; |
| 7086 } | 7158 } |
| 7087 // When we set the is_extensible flag to false we always force | 7159 // When we set the is_extensible flag to false we always force |
| 7088 // the element into dictionary mode (and force them to stay there). | 7160 // the element into dictionary mode (and force them to stay there). |
| 7089 if (!map()->is_extensible()) { | 7161 if (!map()->is_extensible()) { |
| 7090 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7162 Handle<Object> number(Factory::NewNumberFromUint(index)); |
| 7091 Handle<String> index_string(Factory::NumberToString(number)); | 7163 Handle<String> index_string(Factory::NumberToString(number)); |
| 7092 Handle<Object> args[1] = { index_string }; | 7164 Handle<Object> args[1] = { index_string }; |
| 7093 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 7165 return Top::Throw(*Factory::NewTypeError("object_not_extensible", |
| 7094 HandleVector(args, 1))); | 7166 HandleVector(args, 1))); |
| 7095 } | 7167 } |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7975 Object* AsObject() { return string_; } | 8047 Object* AsObject() { return string_; } |
| 7976 | 8048 |
| 7977 String* string_; | 8049 String* string_; |
| 7978 uint32_t hash_; | 8050 uint32_t hash_; |
| 7979 }; | 8051 }; |
| 7980 | 8052 |
| 7981 | 8053 |
| 7982 // StringSharedKeys are used as keys in the eval cache. | 8054 // StringSharedKeys are used as keys in the eval cache. |
| 7983 class StringSharedKey : public HashTableKey { | 8055 class StringSharedKey : public HashTableKey { |
| 7984 public: | 8056 public: |
| 7985 StringSharedKey(String* source, SharedFunctionInfo* shared) | 8057 StringSharedKey(String* source, |
| 7986 : source_(source), shared_(shared) { } | 8058 SharedFunctionInfo* shared, |
| 8059 StrictModeFlag strict_mode) |
| 8060 : source_(source), |
| 8061 shared_(shared), |
| 8062 strict_mode_(strict_mode) { } |
| 7987 | 8063 |
| 7988 bool IsMatch(Object* other) { | 8064 bool IsMatch(Object* other) { |
| 7989 if (!other->IsFixedArray()) return false; | 8065 if (!other->IsFixedArray()) return false; |
| 7990 FixedArray* pair = FixedArray::cast(other); | 8066 FixedArray* pair = FixedArray::cast(other); |
| 7991 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 8067 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 7992 if (shared != shared_) return false; | 8068 if (shared != shared_) return false; |
| 8069 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( |
| 8070 Smi::cast(pair->get(2))->value()); |
| 8071 if (strict_mode != strict_mode_) return false; |
| 7993 String* source = String::cast(pair->get(1)); | 8072 String* source = String::cast(pair->get(1)); |
| 7994 return source->Equals(source_); | 8073 return source->Equals(source_); |
| 7995 } | 8074 } |
| 7996 | 8075 |
| 7997 static uint32_t StringSharedHashHelper(String* source, | 8076 static uint32_t StringSharedHashHelper(String* source, |
| 7998 SharedFunctionInfo* shared) { | 8077 SharedFunctionInfo* shared, |
| 8078 StrictModeFlag strict_mode) { |
| 7999 uint32_t hash = source->Hash(); | 8079 uint32_t hash = source->Hash(); |
| 8000 if (shared->HasSourceCode()) { | 8080 if (shared->HasSourceCode()) { |
| 8001 // Instead of using the SharedFunctionInfo pointer in the hash | 8081 // Instead of using the SharedFunctionInfo pointer in the hash |
| 8002 // code computation, we use a combination of the hash of the | 8082 // code computation, we use a combination of the hash of the |
| 8003 // script source code and the start and end positions. We do | 8083 // script source code and the start and end positions. We do |
| 8004 // this to ensure that the cache entries can survive garbage | 8084 // this to ensure that the cache entries can survive garbage |
| 8005 // collection. | 8085 // collection. |
| 8006 Script* script = Script::cast(shared->script()); | 8086 Script* script = Script::cast(shared->script()); |
| 8007 hash ^= String::cast(script->source())->Hash(); | 8087 hash ^= String::cast(script->source())->Hash(); |
| 8088 if (strict_mode == kStrictMode) hash ^= 0x8000; |
| 8008 hash += shared->start_position(); | 8089 hash += shared->start_position(); |
| 8009 } | 8090 } |
| 8010 return hash; | 8091 return hash; |
| 8011 } | 8092 } |
| 8012 | 8093 |
| 8013 uint32_t Hash() { | 8094 uint32_t Hash() { |
| 8014 return StringSharedHashHelper(source_, shared_); | 8095 return StringSharedHashHelper(source_, shared_, strict_mode_); |
| 8015 } | 8096 } |
| 8016 | 8097 |
| 8017 uint32_t HashForObject(Object* obj) { | 8098 uint32_t HashForObject(Object* obj) { |
| 8018 FixedArray* pair = FixedArray::cast(obj); | 8099 FixedArray* pair = FixedArray::cast(obj); |
| 8019 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 8100 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 8020 String* source = String::cast(pair->get(1)); | 8101 String* source = String::cast(pair->get(1)); |
| 8021 return StringSharedHashHelper(source, shared); | 8102 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( |
| 8103 Smi::cast(pair->get(2))->value()); |
| 8104 return StringSharedHashHelper(source, shared, strict_mode); |
| 8022 } | 8105 } |
| 8023 | 8106 |
| 8024 MUST_USE_RESULT MaybeObject* AsObject() { | 8107 MUST_USE_RESULT MaybeObject* AsObject() { |
| 8025 Object* obj; | 8108 Object* obj; |
| 8026 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2); | 8109 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(3); |
| 8027 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8110 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8028 } | 8111 } |
| 8029 FixedArray* pair = FixedArray::cast(obj); | 8112 FixedArray* pair = FixedArray::cast(obj); |
| 8030 pair->set(0, shared_); | 8113 pair->set(0, shared_); |
| 8031 pair->set(1, source_); | 8114 pair->set(1, source_); |
| 8115 pair->set(2, Smi::FromInt(strict_mode_)); |
| 8032 return pair; | 8116 return pair; |
| 8033 } | 8117 } |
| 8034 | 8118 |
| 8035 private: | 8119 private: |
| 8036 String* source_; | 8120 String* source_; |
| 8037 SharedFunctionInfo* shared_; | 8121 SharedFunctionInfo* shared_; |
| 8122 StrictModeFlag strict_mode_; |
| 8038 }; | 8123 }; |
| 8039 | 8124 |
| 8040 | 8125 |
| 8041 // RegExpKey carries the source and flags of a regular expression as key. | 8126 // RegExpKey carries the source and flags of a regular expression as key. |
| 8042 class RegExpKey : public HashTableKey { | 8127 class RegExpKey : public HashTableKey { |
| 8043 public: | 8128 public: |
| 8044 RegExpKey(String* string, JSRegExp::Flags flags) | 8129 RegExpKey(String* string, JSRegExp::Flags flags) |
| 8045 : string_(string), | 8130 : string_(string), |
| 8046 flags_(Smi::FromInt(flags.value())) { } | 8131 flags_(Smi::FromInt(flags.value())) { } |
| 8047 | 8132 |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8516 return Smi::FromInt(-1); | 8601 return Smi::FromInt(-1); |
| 8517 } | 8602 } |
| 8518 uint32_t key = NumberToUint32(k); | 8603 uint32_t key = NumberToUint32(k); |
| 8519 // In the following we assert that adding the entry to the new dictionary | 8604 // In the following we assert that adding the entry to the new dictionary |
| 8520 // does not cause GC. This is the case because we made sure to allocate | 8605 // does not cause GC. This is the case because we made sure to allocate |
| 8521 // the dictionary big enough above, so it need not grow. | 8606 // the dictionary big enough above, so it need not grow. |
| 8522 if (key < limit) { | 8607 if (key < limit) { |
| 8523 if (value->IsUndefined()) { | 8608 if (value->IsUndefined()) { |
| 8524 undefs++; | 8609 undefs++; |
| 8525 } else { | 8610 } else { |
| 8611 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8612 // Adding an entry with the key beyond smi-range requires |
| 8613 // allocation. Bailout. |
| 8614 return Smi::FromInt(-1); |
| 8615 } |
| 8526 new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked(); | 8616 new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked(); |
| 8527 pos++; | 8617 pos++; |
| 8528 } | 8618 } |
| 8529 } else { | 8619 } else { |
| 8620 if (key > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8621 // Adding an entry with the key beyond smi-range requires |
| 8622 // allocation. Bailout. |
| 8623 return Smi::FromInt(-1); |
| 8624 } |
| 8530 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); | 8625 new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); |
| 8531 } | 8626 } |
| 8532 } | 8627 } |
| 8533 } | 8628 } |
| 8534 | 8629 |
| 8535 uint32_t result = pos; | 8630 uint32_t result = pos; |
| 8536 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); | 8631 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); |
| 8537 while (undefs > 0) { | 8632 while (undefs > 0) { |
| 8633 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8634 // Adding an entry with the key beyond smi-range requires |
| 8635 // allocation. Bailout. |
| 8636 return Smi::FromInt(-1); |
| 8637 } |
| 8538 new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details)-> | 8638 new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details)-> |
| 8539 ToObjectUnchecked(); | 8639 ToObjectUnchecked(); |
| 8540 pos++; | 8640 pos++; |
| 8541 undefs--; | 8641 undefs--; |
| 8542 } | 8642 } |
| 8543 | 8643 |
| 8544 set_elements(new_dict); | 8644 set_elements(new_dict); |
| 8545 | 8645 |
| 8546 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 8646 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8547 return Smi::FromInt(static_cast<int>(result)); | 8647 return Smi::FromInt(static_cast<int>(result)); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8986 | 9086 |
| 8987 | 9087 |
| 8988 Object* CompilationCacheTable::Lookup(String* src) { | 9088 Object* CompilationCacheTable::Lookup(String* src) { |
| 8989 StringKey key(src); | 9089 StringKey key(src); |
| 8990 int entry = FindEntry(&key); | 9090 int entry = FindEntry(&key); |
| 8991 if (entry == kNotFound) return Heap::undefined_value(); | 9091 if (entry == kNotFound) return Heap::undefined_value(); |
| 8992 return get(EntryToIndex(entry) + 1); | 9092 return get(EntryToIndex(entry) + 1); |
| 8993 } | 9093 } |
| 8994 | 9094 |
| 8995 | 9095 |
| 8996 Object* CompilationCacheTable::LookupEval(String* src, Context* context) { | 9096 Object* CompilationCacheTable::LookupEval(String* src, |
| 8997 StringSharedKey key(src, context->closure()->shared()); | 9097 Context* context, |
| 9098 StrictModeFlag strict_mode) { |
| 9099 StringSharedKey key(src, context->closure()->shared(), strict_mode); |
| 8998 int entry = FindEntry(&key); | 9100 int entry = FindEntry(&key); |
| 8999 if (entry == kNotFound) return Heap::undefined_value(); | 9101 if (entry == kNotFound) return Heap::undefined_value(); |
| 9000 return get(EntryToIndex(entry) + 1); | 9102 return get(EntryToIndex(entry) + 1); |
| 9001 } | 9103 } |
| 9002 | 9104 |
| 9003 | 9105 |
| 9004 Object* CompilationCacheTable::LookupRegExp(String* src, | 9106 Object* CompilationCacheTable::LookupRegExp(String* src, |
| 9005 JSRegExp::Flags flags) { | 9107 JSRegExp::Flags flags) { |
| 9006 RegExpKey key(src, flags); | 9108 RegExpKey key(src, flags); |
| 9007 int entry = FindEntry(&key); | 9109 int entry = FindEntry(&key); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 9022 int entry = cache->FindInsertionEntry(key.Hash()); | 9124 int entry = cache->FindInsertionEntry(key.Hash()); |
| 9023 cache->set(EntryToIndex(entry), src); | 9125 cache->set(EntryToIndex(entry), src); |
| 9024 cache->set(EntryToIndex(entry) + 1, value); | 9126 cache->set(EntryToIndex(entry) + 1, value); |
| 9025 cache->ElementAdded(); | 9127 cache->ElementAdded(); |
| 9026 return cache; | 9128 return cache; |
| 9027 } | 9129 } |
| 9028 | 9130 |
| 9029 | 9131 |
| 9030 MaybeObject* CompilationCacheTable::PutEval(String* src, | 9132 MaybeObject* CompilationCacheTable::PutEval(String* src, |
| 9031 Context* context, | 9133 Context* context, |
| 9032 Object* value) { | 9134 SharedFunctionInfo* value) { |
| 9033 StringSharedKey key(src, context->closure()->shared()); | 9135 StringSharedKey key(src, |
| 9136 context->closure()->shared(), |
| 9137 value->strict_mode() ? kStrictMode : kNonStrictMode); |
| 9034 Object* obj; | 9138 Object* obj; |
| 9035 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 9139 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 9036 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9140 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9037 } | 9141 } |
| 9038 | 9142 |
| 9039 CompilationCacheTable* cache = | 9143 CompilationCacheTable* cache = |
| 9040 reinterpret_cast<CompilationCacheTable*>(obj); | 9144 reinterpret_cast<CompilationCacheTable*>(obj); |
| 9041 int entry = cache->FindInsertionEntry(key.Hash()); | 9145 int entry = cache->FindInsertionEntry(key.Hash()); |
| 9042 | 9146 |
| 9043 Object* k; | 9147 Object* k; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9252 // Update the number of elements. | 9356 // Update the number of elements. |
| 9253 ElementsRemoved(removed_entries); | 9357 ElementsRemoved(removed_entries); |
| 9254 } | 9358 } |
| 9255 | 9359 |
| 9256 | 9360 |
| 9257 template<typename Shape, typename Key> | 9361 template<typename Shape, typename Key> |
| 9258 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, | 9362 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 9259 JSObject::DeleteMode mode) { | 9363 JSObject::DeleteMode mode) { |
| 9260 PropertyDetails details = DetailsAt(entry); | 9364 PropertyDetails details = DetailsAt(entry); |
| 9261 // Ignore attributes if forcing a deletion. | 9365 // Ignore attributes if forcing a deletion. |
| 9262 if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) { | 9366 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { |
| 9263 return Heap::false_value(); | 9367 return Heap::false_value(); |
| 9264 } | 9368 } |
| 9265 SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); | 9369 SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); |
| 9266 HashTable<Shape, Key>::ElementRemoved(); | 9370 HashTable<Shape, Key>::ElementRemoved(); |
| 9267 return Heap::true_value(); | 9371 return Heap::true_value(); |
| 9268 } | 9372 } |
| 9269 | 9373 |
| 9270 | 9374 |
| 9271 template<typename Shape, typename Key> | 9375 template<typename Shape, typename Key> |
| 9272 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { | 9376 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9867 if (break_point_objects()->IsUndefined()) return 0; | 9971 if (break_point_objects()->IsUndefined()) return 0; |
| 9868 // Single beak point. | 9972 // Single beak point. |
| 9869 if (!break_point_objects()->IsFixedArray()) return 1; | 9973 if (!break_point_objects()->IsFixedArray()) return 1; |
| 9870 // Multiple break points. | 9974 // Multiple break points. |
| 9871 return FixedArray::cast(break_point_objects())->length(); | 9975 return FixedArray::cast(break_point_objects())->length(); |
| 9872 } | 9976 } |
| 9873 #endif | 9977 #endif |
| 9874 | 9978 |
| 9875 | 9979 |
| 9876 } } // namespace v8::internal | 9980 } } // namespace v8::internal |
| OLD | NEW |